emilsoftware-utilities 2.0.0-dev.23 → 2.0.0-dev.25

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 (261) hide show
  1. package/README.MD +147 -0
  2. package/dist/ContractGenerator.d.ts +4 -3
  3. package/dist/ContractGenerator.js +15 -5
  4. package/dist/ContractGenerator.js.map +1 -1
  5. package/dist/DailyFileTransport.d.ts +8 -2
  6. package/dist/DailyFileTransport.js +9 -2
  7. package/dist/DailyFileTransport.js.map +1 -1
  8. package/dist/DatabaseUpdater.js +8 -3
  9. package/dist/DatabaseUpdater.js.map +1 -1
  10. package/dist/ExecutionTimeLogger.d.ts +2 -2
  11. package/dist/ExecutionTimeLogger.js +3 -2
  12. package/dist/ExecutionTimeLogger.js.map +1 -1
  13. package/dist/Logger.d.ts +22 -9
  14. package/dist/Logger.js +131 -54
  15. package/dist/Logger.js.map +1 -1
  16. package/dist/Orm.d.ts +26 -6
  17. package/dist/Orm.js +144 -40
  18. package/dist/Orm.js.map +1 -1
  19. package/dist/Utilities.d.ts +12 -7
  20. package/dist/Utilities.js +57 -22
  21. package/dist/Utilities.js.map +1 -1
  22. package/dist/accessi-module/AccessiModule.d.ts +9 -0
  23. package/dist/accessi-module/AccessiModule.js +12 -4
  24. package/dist/accessi-module/AccessiModule.js.map +1 -1
  25. package/dist/accessi-module/Console/console.css +529 -281
  26. package/dist/accessi-module/Console/console.js +2081 -85
  27. package/dist/accessi-module/Console/console.js.map +1 -1
  28. package/dist/accessi-module/Console/generated/accessiApi.d.ts +167 -1
  29. package/dist/accessi-module/Console/generated/accessiApi.js +156 -2
  30. package/dist/accessi-module/Console/generated/accessiApi.js.map +1 -1
  31. package/dist/accessi-module/Console/generated/model/abilitazioneMenu.d.ts +20 -8
  32. package/dist/accessi-module/Console/generated/model/abilitazioneMenu.js.map +1 -1
  33. package/dist/accessi-module/Console/generated/model/createFilterTypeRequest.d.ts +23 -0
  34. package/dist/accessi-module/Console/generated/model/createFilterTypeRequest.js +3 -0
  35. package/dist/accessi-module/Console/generated/model/createFilterTypeRequest.js.map +1 -0
  36. package/dist/accessi-module/Console/generated/model/createFilterTypeRequestFlgEnabled.d.ts +14 -0
  37. package/dist/accessi-module/Console/generated/model/createFilterTypeRequestFlgEnabled.js +15 -0
  38. package/dist/accessi-module/Console/generated/model/createFilterTypeRequestFlgEnabled.js.map +1 -0
  39. package/dist/accessi-module/Console/generated/model/createMenuGroupRequest.d.ts +27 -0
  40. package/dist/accessi-module/Console/generated/model/createMenuGroupRequest.js +9 -0
  41. package/dist/accessi-module/Console/generated/model/createMenuGroupRequest.js.map +1 -0
  42. package/dist/accessi-module/Console/generated/model/createMenuRequest.d.ts +52 -0
  43. package/dist/accessi-module/Console/generated/model/createMenuRequest.js +9 -0
  44. package/dist/accessi-module/Console/generated/model/createMenuRequest.js.map +1 -0
  45. package/dist/accessi-module/Console/generated/model/createMenuTypeRequest.d.ts +18 -0
  46. package/dist/accessi-module/Console/generated/model/createMenuTypeRequest.js +9 -0
  47. package/dist/accessi-module/Console/generated/model/createMenuTypeRequest.js.map +1 -0
  48. package/dist/accessi-module/Console/generated/model/createServiceTokenRequest.d.ts +16 -0
  49. package/dist/accessi-module/Console/generated/model/createServiceTokenRequest.js +9 -0
  50. package/dist/accessi-module/Console/generated/model/createServiceTokenRequest.js.map +1 -0
  51. package/dist/accessi-module/Console/generated/model/createServiceTokenResponse.d.ts +14 -0
  52. package/dist/accessi-module/Console/generated/model/createServiceTokenResponse.js +3 -0
  53. package/dist/accessi-module/Console/generated/model/createServiceTokenResponse.js.map +1 -0
  54. package/dist/accessi-module/Console/generated/model/getMenuTypesResponse.d.ts +14 -0
  55. package/dist/accessi-module/Console/generated/model/getMenuTypesResponse.js +3 -0
  56. package/dist/accessi-module/Console/generated/model/getMenuTypesResponse.js.map +1 -0
  57. package/dist/accessi-module/Console/generated/model/getServiceTokensParams.d.ts +12 -0
  58. package/dist/accessi-module/Console/generated/model/getServiceTokensParams.js +9 -0
  59. package/dist/accessi-module/Console/generated/model/getServiceTokensParams.js.map +1 -0
  60. package/dist/accessi-module/Console/generated/model/getServiceTokensResponse.d.ts +14 -0
  61. package/dist/accessi-module/Console/generated/model/getServiceTokensResponse.js +3 -0
  62. package/dist/accessi-module/Console/generated/model/getServiceTokensResponse.js.map +1 -0
  63. package/dist/accessi-module/Console/generated/model/getUsersParams.d.ts +8 -0
  64. package/dist/accessi-module/Console/generated/model/getUsersParams.js.map +1 -1
  65. package/dist/accessi-module/Console/generated/model/index.d.ts +18 -0
  66. package/dist/accessi-module/Console/generated/model/index.js +18 -0
  67. package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
  68. package/dist/accessi-module/Console/generated/model/issuedServiceTokenDto.d.ts +30 -0
  69. package/dist/accessi-module/Console/generated/model/issuedServiceTokenDto.js +9 -0
  70. package/dist/accessi-module/Console/generated/model/issuedServiceTokenDto.js.map +1 -0
  71. package/dist/accessi-module/Console/generated/model/menuTypeEntity.d.ts +12 -0
  72. package/dist/accessi-module/Console/generated/model/menuTypeEntity.js +9 -0
  73. package/dist/accessi-module/Console/generated/model/menuTypeEntity.js.map +1 -0
  74. package/dist/accessi-module/Console/generated/model/serviceTokenDto.d.ts +28 -0
  75. package/dist/accessi-module/Console/generated/model/serviceTokenDto.js +9 -0
  76. package/dist/accessi-module/Console/generated/model/serviceTokenDto.js.map +1 -0
  77. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequest.d.ts +21 -0
  78. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequest.js +3 -0
  79. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequest.js.map +1 -0
  80. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequestFlgEnabled.d.ts +14 -0
  81. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequestFlgEnabled.js +15 -0
  82. package/dist/accessi-module/Console/generated/model/updateFilterTypeRequestFlgEnabled.js.map +1 -0
  83. package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.d.ts +22 -0
  84. package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.js +9 -0
  85. package/dist/accessi-module/Console/generated/model/updateMenuGroupRequest.js.map +1 -0
  86. package/dist/accessi-module/Console/generated/model/updateMenuRequest.d.ts +47 -0
  87. package/dist/accessi-module/Console/generated/model/updateMenuRequest.js +9 -0
  88. package/dist/accessi-module/Console/generated/model/updateMenuRequest.js.map +1 -0
  89. package/dist/accessi-module/Console/generated/model/updateMenuTypeRequest.d.ts +13 -0
  90. package/dist/accessi-module/Console/generated/model/updateMenuTypeRequest.js +9 -0
  91. package/dist/accessi-module/Console/generated/model/updateMenuTypeRequest.js.map +1 -0
  92. package/dist/accessi-module/Console/help.d.ts +13 -0
  93. package/dist/accessi-module/Console/help.js +348 -0
  94. package/dist/accessi-module/Console/help.js.map +1 -0
  95. package/dist/accessi-module/Console/index.html +89 -21
  96. package/dist/accessi-module/Console/wiki.d.ts +52 -0
  97. package/dist/accessi-module/Console/wiki.js +689 -0
  98. package/dist/accessi-module/Console/wiki.js.map +1 -0
  99. package/dist/accessi-module/Controllers/AccessiConsoleController.d.ts +8 -1
  100. package/dist/accessi-module/Controllers/AccessiConsoleController.js +52 -15
  101. package/dist/accessi-module/Controllers/AccessiConsoleController.js.map +1 -1
  102. package/dist/accessi-module/Controllers/ConfiguratorController.d.ts +1 -3
  103. package/dist/accessi-module/Controllers/ConfiguratorController.js +6 -8
  104. package/dist/accessi-module/Controllers/ConfiguratorController.js.map +1 -1
  105. package/dist/accessi-module/Controllers/EmailController.d.ts +1 -1
  106. package/dist/accessi-module/Controllers/EmailController.js +1 -1
  107. package/dist/accessi-module/Controllers/EmailController.js.map +1 -1
  108. package/dist/accessi-module/Controllers/FiltriController.d.ts +5 -4
  109. package/dist/accessi-module/Controllers/FiltriController.js +92 -4
  110. package/dist/accessi-module/Controllers/FiltriController.js.map +1 -1
  111. package/dist/accessi-module/Controllers/PermissionController.d.ts +11 -0
  112. package/dist/accessi-module/Controllers/PermissionController.js +273 -8
  113. package/dist/accessi-module/Controllers/PermissionController.js.map +1 -1
  114. package/dist/accessi-module/Controllers/ServiceTokenController.d.ts +23 -0
  115. package/dist/accessi-module/Controllers/ServiceTokenController.js +176 -0
  116. package/dist/accessi-module/Controllers/ServiceTokenController.js.map +1 -0
  117. package/dist/accessi-module/Controllers/UserController.d.ts +2 -2
  118. package/dist/accessi-module/Controllers/UserController.js +25 -9
  119. package/dist/accessi-module/Controllers/UserController.js.map +1 -1
  120. package/dist/accessi-module/Dtos/Abilitazione.js.map +1 -1
  121. package/dist/accessi-module/Dtos/AbilitazioneMenu.js +16 -8
  122. package/dist/accessi-module/Dtos/AbilitazioneMenu.js.map +1 -1
  123. package/dist/accessi-module/Dtos/AssignPermissionsToUserRequest.js.map +1 -1
  124. package/dist/accessi-module/Dtos/AssignRolesToUserRequest.js.map +1 -1
  125. package/dist/accessi-module/Dtos/AuthenticatedUserPayloadDto.js.map +1 -1
  126. package/dist/accessi-module/Dtos/BaseResponse.js.map +1 -1
  127. package/dist/accessi-module/Dtos/CatalogDtos.d.ts +66 -0
  128. package/dist/accessi-module/Dtos/CatalogDtos.js +336 -0
  129. package/dist/accessi-module/Dtos/CatalogDtos.js.map +1 -0
  130. package/dist/accessi-module/Dtos/ConfirmResetPasswordRequest.js.map +1 -1
  131. package/dist/accessi-module/Dtos/FiltriUtente.js.map +1 -1
  132. package/dist/accessi-module/Dtos/GetGroupsWithMenusResponse.js.map +1 -1
  133. package/dist/accessi-module/Dtos/GetMenusResponse.js +1 -1
  134. package/dist/accessi-module/Dtos/GetMenusResponse.js.map +1 -1
  135. package/dist/accessi-module/Dtos/GetRolesResponse.js.map +1 -1
  136. package/dist/accessi-module/Dtos/GetUserByTokenRequest.js.map +1 -1
  137. package/dist/accessi-module/Dtos/GetUserByTokenResponse.js.map +1 -1
  138. package/dist/accessi-module/Dtos/GetUsersResponse.d.ts +1 -1
  139. package/dist/accessi-module/Dtos/GetUsersResponse.js.map +1 -1
  140. package/dist/accessi-module/Dtos/LoginRequest.js.map +1 -1
  141. package/dist/accessi-module/Dtos/LoginResponse.d.ts +1 -1
  142. package/dist/accessi-module/Dtos/LoginResponse.js +1 -1
  143. package/dist/accessi-module/Dtos/LoginResponse.js.map +1 -1
  144. package/dist/accessi-module/Dtos/MenuItem.js +1 -0
  145. package/dist/accessi-module/Dtos/Permission.js.map +1 -1
  146. package/dist/accessi-module/Dtos/RegisterRequest.js +2 -1
  147. package/dist/accessi-module/Dtos/RegisterRequest.js.map +1 -1
  148. package/dist/accessi-module/Dtos/RegisterResponse.js.map +1 -1
  149. package/dist/accessi-module/Dtos/Role.js.map +1 -1
  150. package/dist/accessi-module/Dtos/RuoliMenu.js.map +1 -1
  151. package/dist/accessi-module/Dtos/SendResetPasswordEmailRequest.js.map +1 -1
  152. package/dist/accessi-module/Dtos/ServiceToken.d.ts +34 -0
  153. package/dist/accessi-module/Dtos/ServiceToken.js +128 -0
  154. package/dist/accessi-module/Dtos/ServiceToken.js.map +1 -0
  155. package/dist/accessi-module/Dtos/SetStatoRegistrazione.js.map +1 -1
  156. package/dist/accessi-module/Dtos/TipoFiltro.js.map +1 -1
  157. package/dist/accessi-module/Dtos/TokenResult.js.map +1 -1
  158. package/dist/accessi-module/Dtos/TwoFactorDtos.js.map +1 -1
  159. package/dist/accessi-module/Dtos/UpdateEnabledStatusRequest.js.map +1 -1
  160. package/dist/accessi-module/Dtos/UserDto.js +4 -2
  161. package/dist/accessi-module/Dtos/UserDto.js.map +1 -1
  162. package/dist/accessi-module/Dtos/UserGrantsDto.js.map +1 -1
  163. package/dist/accessi-module/Dtos/UserGrantsResponse.js.map +1 -1
  164. package/dist/accessi-module/Dtos/index.d.ts +2 -0
  165. package/dist/accessi-module/Dtos/index.js +2 -0
  166. package/dist/accessi-module/Dtos/index.js.map +1 -1
  167. package/dist/accessi-module/Services/AuthService/AuthService.d.ts +2 -2
  168. package/dist/accessi-module/Services/AuthService/AuthService.js +36 -36
  169. package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
  170. package/dist/accessi-module/Services/EmailService/EmailService.d.ts +2 -1
  171. package/dist/accessi-module/Services/EmailService/EmailService.js +9 -6
  172. package/dist/accessi-module/Services/EmailService/EmailService.js.map +1 -1
  173. package/dist/accessi-module/Services/FiltriService/FiltriService.d.ts +10 -3
  174. package/dist/accessi-module/Services/FiltriService/FiltriService.js +64 -6
  175. package/dist/accessi-module/Services/FiltriService/FiltriService.js.map +1 -1
  176. package/dist/accessi-module/Services/PermissionService/PermissionService.d.ts +44 -1
  177. package/dist/accessi-module/Services/PermissionService/PermissionService.js +418 -110
  178. package/dist/accessi-module/Services/PermissionService/PermissionService.js.map +1 -1
  179. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.d.ts +75 -0
  180. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js +265 -0
  181. package/dist/accessi-module/Services/ServiceTokenService/ServiceTokenService.js.map +1 -0
  182. package/dist/accessi-module/Services/TwoFactorService/TwoFactorService.js +23 -27
  183. package/dist/accessi-module/Services/TwoFactorService/TwoFactorService.js.map +1 -1
  184. package/dist/accessi-module/Services/UserService/UserService.d.ts +10 -3
  185. package/dist/accessi-module/Services/UserService/UserService.js +170 -84
  186. package/dist/accessi-module/Services/UserService/UserService.js.map +1 -1
  187. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.d.ts +9 -0
  188. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js +76 -28
  189. package/dist/accessi-module/database-updates/AccessiDatabaseUpdater.js.map +1 -1
  190. package/dist/accessi-module/database-updates/accessiSchema.d.ts +1 -1
  191. package/dist/accessi-module/database-updates/accessiSchema.js +9 -1
  192. package/dist/accessi-module/database-updates/accessiSchema.js.map +1 -1
  193. package/dist/accessi-module/database-updates/optionalColumns.d.ts +2 -0
  194. package/dist/accessi-module/database-updates/optionalColumns.js +33 -1
  195. package/dist/accessi-module/database-updates/optionalColumns.js.map +1 -1
  196. package/dist/accessi-module/database-updates/runAccessiDbUpdate.js +7 -2
  197. package/dist/accessi-module/database-updates/runAccessiDbUpdate.js.map +1 -1
  198. package/dist/accessi-module/federated-auth/FederatedAuthController.d.ts +1 -0
  199. package/dist/accessi-module/federated-auth/FederatedAuthController.js +26 -0
  200. package/dist/accessi-module/federated-auth/FederatedAuthController.js.map +1 -1
  201. package/dist/accessi-module/federated-auth/FederatedAuthService.d.ts +6 -0
  202. package/dist/accessi-module/federated-auth/FederatedAuthService.js +28 -1
  203. package/dist/accessi-module/federated-auth/FederatedAuthService.js.map +1 -1
  204. package/dist/accessi-module/index.d.ts +4 -1
  205. package/dist/accessi-module/index.js +8 -2
  206. package/dist/accessi-module/index.js.map +1 -1
  207. package/dist/accessi-module/jwt/jwt.strategy.js +8 -5
  208. package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
  209. package/dist/accessi-module/middleware/accessiRequirements.d.ts +1 -1
  210. package/dist/accessi-module/middleware/accessiRequirements.js.map +1 -1
  211. package/dist/accessi-module/middleware/authenticateGen.js +11 -7
  212. package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
  213. package/dist/accessi-module/security/accessControl.js +8 -3
  214. package/dist/accessi-module/security/accessControl.js.map +1 -1
  215. package/dist/accessi-module/security/authenticatedToken.d.ts +1 -1
  216. package/dist/accessi-module/security/authenticatedToken.js +2 -1
  217. package/dist/accessi-module/security/authenticatedToken.js.map +1 -1
  218. package/dist/accessi-module/security/passwordResetToken.d.ts +9 -3
  219. package/dist/accessi-module/security/passwordResetToken.js +9 -5
  220. package/dist/accessi-module/security/passwordResetToken.js.map +1 -1
  221. package/dist/accessi-module/security/publicAuthRateLimit.d.ts +1 -1
  222. package/dist/accessi-module/security/publicAuthRateLimit.js +28 -8
  223. package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
  224. package/dist/accessi-module/security/serviceTokenGuard.d.ts +25 -0
  225. package/dist/accessi-module/security/serviceTokenGuard.js +85 -0
  226. package/dist/accessi-module/security/serviceTokenGuard.js.map +1 -0
  227. package/dist/accessi-module/security/serviceTokenRateLimit.d.ts +8 -0
  228. package/dist/accessi-module/security/serviceTokenRateLimit.js +49 -0
  229. package/dist/accessi-module/security/serviceTokenRateLimit.js.map +1 -0
  230. package/dist/allegati-module/AllegatiModule.d.ts +11 -0
  231. package/dist/allegati-module/AllegatiModule.js +11 -1
  232. package/dist/allegati-module/AllegatiModule.js.map +1 -1
  233. package/dist/allegati-module/Controllers/AllegatiController.d.ts +2 -1
  234. package/dist/allegati-module/Controllers/AllegatiController.js +23 -15
  235. package/dist/allegati-module/Controllers/AllegatiController.js.map +1 -1
  236. package/dist/allegati-module/Dtos/AllegatoDto.js.map +1 -1
  237. package/dist/allegati-module/Dtos/BaseResponse.js.map +1 -1
  238. package/dist/allegati-module/Dtos/UploadSingleFileRequest.js.map +1 -1
  239. package/dist/allegati-module/Dtos/responses/DownloadAllegatoResponseDto.js.map +1 -1
  240. package/dist/allegati-module/Dtos/responses/GetListResponse.js.map +1 -1
  241. package/dist/allegati-module/Dtos/responses/UploadAllegatoResponseDto.js.map +1 -1
  242. package/dist/allegati-module/Services/AllegatiService/AllegatiService.d.ts +10 -3
  243. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js +101 -52
  244. package/dist/allegati-module/Services/AllegatiService/AllegatiService.js.map +1 -1
  245. package/dist/allegati-module/security/allegatiAuthorizationGuard.d.ts +14 -0
  246. package/dist/allegati-module/security/allegatiAuthorizationGuard.js +70 -0
  247. package/dist/allegati-module/security/allegatiAuthorizationGuard.js.map +1 -0
  248. package/dist/autobind.d.ts +10 -3
  249. package/dist/autobind.js +24 -9
  250. package/dist/autobind.js.map +1 -1
  251. package/dist/emilsoftware-utilities-2.0.0-dev.25.tgz +0 -0
  252. package/dist/firebird-compat.d.ts +13 -0
  253. package/dist/firebird-compat.js +3 -2
  254. package/dist/firebird-compat.js.map +1 -1
  255. package/dist/scripts/generateAccessiWiki.d.ts +1 -0
  256. package/dist/scripts/generateAccessiWiki.js +131 -0
  257. package/dist/scripts/generateAccessiWiki.js.map +1 -0
  258. package/dist/swagger/SwaggerConfig.js +6 -3
  259. package/dist/swagger/SwaggerConfig.js.map +1 -1
  260. package/package.json +19 -8
  261. package/dist/emilsoftware-utilities-2.0.0-dev.23.tgz +0 -0
@@ -1,17 +1,52 @@
1
+ /* =========================================================================
2
+ Accessi Console — design system
3
+ Spaziature su griglia 8pt (sub-grid 4px), type scale ~1.2,
4
+ contrasto WCAG AA, gerarchia affidata a tipografia e spazio.
5
+ ========================================================================= */
6
+
1
7
  :root {
2
- --canvas: #edf1f4;
8
+ /* Superfici e testo */
9
+ --canvas: #f5f7f8;
3
10
  --surface: #ffffff;
4
- --surface-muted: #f7f9fb;
11
+ --surface-sunken: #f2f4f6;
12
+ --surface-hover: #f6f8f9;
5
13
  --ink: #17212b;
6
- --muted: #607080;
7
- --line: #d8e0e7;
8
- --line-strong: #bdc9d3;
14
+ --ink-2: #3c4a55;
15
+ --muted: #697883;
16
+ --line: #e4e9ed;
17
+ --line-strong: #cfd7de;
18
+
19
+ /* Brand e stato */
9
20
  --brand: #0d5c63;
10
- --brand-strong: #08464c;
11
- --brand-soft: #dff0ef;
21
+ --brand-strong: #0a4a50;
22
+ --brand-soft: #e8f3f2;
23
+ --brand-line: #bfdedb;
12
24
  --danger: #b42318;
13
- --danger-soft: #fff0ee;
14
- --shadow: 0 14px 38px rgb(27 42 54 / 10%);
25
+ --danger-soft: #fdecea;
26
+ --danger-line: #f0c6c2;
27
+ --warn-soft: #fbf3e2;
28
+ --warn-line: #ecd8ab;
29
+ --warn-ink: #7a5a15;
30
+
31
+ /* Spazio (8pt + sub 4px) */
32
+ --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;
33
+
34
+ /* Dimensioni layout */
35
+ --shell-max: 1728px;
36
+ --gutter: clamp(16px, 1.8vw, 32px);
37
+ --sidebar-w: clamp(224px, 17vw, 272px);
38
+
39
+ /* Raggio */
40
+ --r-sm: 6px; --r-md: 8px; --r-lg: 12px; --r-xl: 16px; --r-pill: 999px;
41
+
42
+ /* Ombre sobrie */
43
+ --shadow-sm: 0 1px 2px rgb(16 24 32 / 6%);
44
+ --shadow-md: 0 4px 16px rgb(16 24 32 / 8%);
45
+
46
+ /* Tipografia */
47
+ --font-sans: "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
48
+ --font-mono: "JetBrains Mono", "Cascadia Mono", Consolas, "SFMono-Regular", monospace;
49
+ --fs-xs: 12px; --fs-sm: 13px; --fs-base: 14px; --fs-md: 16px; --fs-lg: 18px; --fs-xl: 22px; --fs-2xl: 28px;
15
50
  }
16
51
 
17
52
  * { box-sizing: border-box; }
@@ -20,346 +55,559 @@ body {
20
55
  min-width: 320px;
21
56
  margin: 0;
22
57
  color: var(--ink);
23
- font-family: "Aptos", "Avenir Next", "Segoe UI", sans-serif;
24
- font-size: 15px;
25
- line-height: 1.45;
26
- background:
27
- radial-gradient(circle at 4% -5%, #d8eeeb 0, transparent 28rem),
28
- linear-gradient(90deg, rgb(13 92 99 / 3%) 1px, transparent 1px),
29
- linear-gradient(rgb(13 92 99 / 3%) 1px, transparent 1px),
30
- var(--canvas);
31
- background-size: auto, 28px 28px, 28px 28px, auto;
58
+ font-family: var(--font-sans);
59
+ font-size: var(--fs-base);
60
+ line-height: 1.5;
61
+ background: var(--canvas);
62
+ -webkit-font-smoothing: antialiased;
32
63
  }
33
64
 
65
+ h1, h2, h3 { color: var(--ink); font-weight: 650; letter-spacing: -.01em; line-height: 1.25; }
66
+ h1 { font-size: var(--fs-2xl); }
67
+ h2 { font-size: var(--fs-xl); margin: 0 0 var(--s1); }
68
+ h3 { font-size: var(--fs-md); margin: 0 0 var(--s3); }
69
+ p { margin: 0 0 var(--s3); }
70
+
34
71
  button, input, select, textarea { font: inherit; }
35
72
  button { cursor: pointer; }
36
- button:disabled { cursor: not-allowed; opacity: .55; }
73
+ button:disabled { cursor: not-allowed; opacity: .5; }
37
74
  button, input, select, textarea { -webkit-tap-highlight-color: transparent; }
38
- button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
39
- outline: 3px solid rgb(13 92 99 / 22%);
75
+ button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, a:focus-visible, summary:focus-visible {
76
+ outline: 2px solid var(--brand);
40
77
  outline-offset: 2px;
78
+ border-radius: var(--r-sm);
41
79
  }
42
80
 
43
- #app { max-width: 1440px; margin: 0 auto; padding: 32px; }
44
81
  [hidden] { display: none !important; }
82
+ ::selection { background: var(--brand-soft); }
45
83
 
46
- #loading-overlay {
47
- position: fixed;
48
- z-index: 1000;
49
- inset: 0;
50
- display: grid;
51
- place-items: center;
52
- padding: 24px;
53
- background: rgb(12 28 39 / 30%);
54
- backdrop-filter: blur(3px);
55
- }
56
- .loading-panel {
57
- display: flex;
58
- align-items: center;
59
- gap: 14px;
60
- width: min(100%, 360px);
61
- padding: 18px 20px;
62
- border: 1px solid rgb(255 255 255 / 65%);
63
- border-radius: 12px;
64
- color: var(--ink);
65
- background: rgb(255 255 255 / 96%);
66
- box-shadow: 0 20px 55px rgb(11 30 42 / 28%);
67
- }
68
- .loading-panel strong, .loading-panel small { display: block; }
69
- .loading-panel small { margin-top: 2px; color: var(--muted); }
70
- .loading-spinner {
71
- width: 25px;
72
- height: 25px;
73
- flex: 0 0 25px;
74
- border: 3px solid #b9d9d7;
75
- border-top-color: var(--brand);
76
- border-radius: 50%;
77
- animation: accessi-spin .75s linear infinite;
84
+ /* ---------------------------------------------------------------- layout */
85
+
86
+ #app {
87
+ width: 100%;
88
+ max-width: var(--shell-max);
89
+ margin-inline: auto;
90
+ padding: var(--gutter);
78
91
  }
79
- @keyframes accessi-spin { to { transform: rotate(360deg); } }
80
92
 
81
- .card, header, #view {
93
+ .card {
94
+ max-width: 400px;
95
+ margin: 8vh auto;
96
+ padding: var(--s6);
82
97
  border: 1px solid var(--line);
98
+ border-radius: var(--r-xl);
83
99
  background: var(--surface);
84
- box-shadow: var(--shadow);
100
+ box-shadow: var(--shadow-md);
85
101
  }
102
+ .card h1 { margin: 0 0 var(--s2); }
103
+ .card > p { margin: 0 0 var(--s5); color: var(--muted); }
104
+ .card form { gap: var(--s4); }
105
+ .card form button, .card > button { width: 100%; }
106
+ .card > button { margin-top: var(--s3); }
86
107
 
87
- .card { max-width: 440px; margin: 10vh auto; padding: 36px; border-radius: 14px; }
88
- .card h1 { margin: 0 0 8px; font-size: 1.8rem; letter-spacing: -.035em; }
89
- .card > p { margin: 0 0 26px; color: var(--muted); }
108
+ #console { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); gap: var(--gutter); align-items: start; }
90
109
 
91
- header {
110
+ .sidebar {
111
+ position: sticky;
112
+ top: var(--gutter);
92
113
  display: flex;
93
- align-items: center;
94
- justify-content: space-between;
95
- min-height: 84px;
96
- padding: 16px 20px 16px 24px;
97
- border-radius: 14px;
98
- border-color: #0b4d54;
114
+ flex-direction: column;
115
+ gap: var(--s4);
116
+ max-height: calc(100vh - 2 * var(--gutter));
117
+ overflow: auto;
118
+ padding: var(--s4);
119
+ border: 1px solid var(--line);
120
+ border-radius: var(--r-lg);
121
+ background: var(--surface);
122
+ box-shadow: var(--shadow-sm);
123
+ }
124
+
125
+ .brand { display: flex; align-items: center; gap: var(--s3); padding: var(--s1); }
126
+ .brand-mark {
127
+ display: grid;
128
+ place-items: center;
129
+ width: 36px;
130
+ height: 36px;
131
+ flex: 0 0 36px;
132
+ border-radius: var(--r-md);
99
133
  color: #fff;
100
- background: linear-gradient(115deg, #0a3d48, var(--brand) 65%, #16757a);
134
+ font-weight: 700;
135
+ font-size: var(--fs-md);
136
+ background: var(--brand);
101
137
  }
138
+ .brand-text { min-width: 0; }
139
+ .brand strong { display: block; font-size: var(--fs-md); }
140
+ .brand small { display: block; overflow: hidden; color: var(--muted); font-size: var(--fs-xs); text-overflow: ellipsis; white-space: nowrap; }
102
141
 
103
- header strong { display: block; font-size: 1.15rem; letter-spacing: -.015em; }
104
- header small { display: block; margin-top: 2px; color: rgb(255 255 255 / 74%); }
142
+ /* Navigazione della sidebar (scoped: NON usare il selettore `nav` nudo,
143
+ altrimenti colpisce anche il paginatore, che è un <nav>). */
144
+ .sidebar nav { display: flex; flex-direction: column; gap: var(--s1); }
145
+ .sidebar nav a {
146
+ display: flex;
147
+ align-items: center;
148
+ gap: var(--s3);
149
+ min-height: 38px;
150
+ padding: var(--s2) var(--s3);
151
+ border-radius: var(--r-md);
152
+ color: var(--ink-2);
153
+ font-size: var(--fs-base);
154
+ font-weight: 550;
155
+ text-decoration: none;
156
+ }
157
+ .sidebar nav a svg { flex: 0 0 18px; width: 18px; height: 18px; opacity: .78; }
158
+ .sidebar nav a:hover { color: var(--ink); background: var(--surface-hover); }
159
+ .sidebar nav a[aria-current="page"] { color: var(--brand-strong); background: var(--brand-soft); font-weight: 650; }
160
+ .sidebar nav a[aria-current="page"] svg { opacity: 1; }
105
161
 
106
- nav {
162
+ /* Navigazione ad albero: voci unitarie e rami con sottomenu */
163
+ .nav-tree { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
164
+ .nav-tree summary {
107
165
  display: flex;
108
- gap: 6px;
109
- margin: 14px 0 16px;
110
- padding: 7px;
111
- overflow-x: auto;
166
+ align-items: center;
167
+ gap: var(--s3);
168
+ padding: var(--s2) var(--s3);
169
+ border-radius: var(--r-sm);
170
+ color: var(--ink-2);
171
+ font-size: var(--fs-sm);
172
+ font-weight: 550;
173
+ cursor: pointer;
174
+ list-style: none;
175
+ }
176
+ .nav-tree summary::-webkit-details-marker { display: none; }
177
+ .nav-tree summary:hover { color: var(--ink); background: var(--surface-hover); }
178
+ .nav-tree summary > svg:first-child { flex: 0 0 18px; width: 18px; height: 18px; opacity: .78; }
179
+ .nav-tree summary > span { flex: 1 1 auto; }
180
+ .nav-chevron { flex: 0 0 14px; width: 14px; height: 14px; opacity: .5; transition: transform .15s ease; }
181
+ details[data-nav-group][open] > summary .nav-chevron { transform: rotate(90deg); }
182
+ details[data-nav-group]:has([aria-current="page"]) > summary { color: var(--brand-strong); background: var(--brand-soft); }
183
+ .nav-tree ul { display: flex; flex-direction: column; gap: 2px; margin: 2px 0 2px var(--s4); padding-left: var(--s3); border-left: 1px solid var(--line); list-style: none; }
184
+ .nav-tree ul a { padding-left: var(--s3); }
185
+ .nav-tree ul a svg { display: none; }
186
+
187
+ .sidebar-logout { justify-content: center; margin-top: var(--s2); }
188
+ .content { min-width: 0; display: grid; gap: var(--s4); }
189
+ .content > h2:first-child, #view > h2:first-child { margin-top: 0; }
190
+
191
+ #view {
192
+ min-height: 60vh;
193
+ padding: clamp(20px, 2vw, 32px);
112
194
  border: 1px solid var(--line);
113
- border-radius: 11px;
114
- background: rgb(255 255 255 / 76%);
195
+ border-radius: var(--r-lg);
196
+ background: var(--surface);
197
+ box-shadow: var(--shadow-sm);
115
198
  }
116
199
 
200
+ /* ------------------------------------------------------------- componenti */
201
+
117
202
  button {
203
+ display: inline-flex;
204
+ align-items: center;
205
+ justify-content: center;
206
+ gap: var(--s2);
118
207
  min-height: 38px;
119
- border: 1px solid var(--brand);
120
- border-radius: 7px;
121
- padding: 8px 13px;
208
+ padding: var(--s2) var(--s4);
209
+ border: 1px solid transparent;
210
+ border-radius: var(--r-md);
122
211
  color: #fff;
123
- font-weight: 650;
212
+ font-size: var(--fs-base);
213
+ font-weight: 600;
214
+ white-space: nowrap;
124
215
  background: var(--brand);
125
- transition: background .15s ease, border-color .15s ease, box-shadow .15s ease, transform .15s ease;
216
+ transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
126
217
  }
127
- button:hover { border-color: var(--brand-strong); background: var(--brand-strong); box-shadow: 0 4px 10px rgb(8 70 76 / 18%); }
128
- button:active { transform: translateY(1px); box-shadow: none; }
129
- nav a { flex: 0 0 auto; min-height: 38px; border: 1px solid transparent; border-radius: 7px; padding: 8px 13px; color: #40525c; font-weight: 650; text-decoration: none; background: transparent; box-shadow: none; }
130
- nav a:hover, nav a[aria-current="page"] { color: #fff; background: var(--brand); }
131
- nav a:focus-visible { outline: 3px solid rgb(13 92 99 / 22%); outline-offset: 2px; }
132
- .secondary { border-color: #d2dbe2; color: #40505b; background: #f6f8fa; }
133
- .secondary:hover { border-color: #b7c4cd; color: #24323b; background: #edf2f5; }
218
+ button:hover { background: var(--brand-strong); }
219
+ button:active { box-shadow: inset 0 1px 3px rgb(0 0 0 / 18%); }
134
220
 
135
- #notice { min-height: 0; }
136
- #notice:not(:empty) { margin-bottom: 14px; padding: 11px 13px; border: 1px solid #b9d9d7; border-radius: 8px; color: #15515a; background: var(--brand-soft); }
137
- #notice .error { color: var(--danger); }
138
- #notice:has(.error) { border-color: #f2c4bf; background: var(--danger-soft); }
139
-
140
- #view { min-height: 420px; padding: 28px; border-radius: 14px; }
141
- #view > h2 { margin: 0 0 6px; font-size: 1.65rem; letter-spacing: -.03em; }
142
- #view > h2 + .muted { display: block; margin-bottom: 24px; }
143
- #back { margin-bottom: 18px; border-color: #d2dbe2; color: #40505b; background: #f6f8fa; }
144
- #back:hover { border-color: #b7c4cd; color: #24323b; background: #edf2f5; }
145
- .page-header { display: flex; align-items: end; justify-content: space-between; gap: 16px; margin: 0 0 24px; padding-bottom: 18px; border-bottom: 1px solid var(--line); }
146
- .page-header h2 { margin: 0; font-size: 1.7rem; letter-spacing: -.035em; }
147
- .eyebrow { margin: 0 0 4px; color: var(--brand); font-size: .72rem; font-weight: 750; letter-spacing: .1em; text-transform: uppercase; }
148
- h3 { margin: 0 0 16px; font-size: 1rem; letter-spacing: -.01em; }
149
-
150
- .toolbar { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 24px; }
221
+ .secondary { border-color: var(--line-strong); color: var(--ink-2); background: var(--surface); }
222
+ .secondary:hover { border-color: #b9c4cc; color: var(--ink); background: var(--surface-sunken); box-shadow: none; }
223
+
224
+ .danger-button { border-color: var(--danger-line); color: var(--danger); background: var(--surface); }
225
+ .danger-button:hover { border-color: var(--danger); color: #fff; background: var(--danger); }
226
+
227
+ .icon-button { width: 38px; min-width: 38px; padding: 0; border-color: var(--line-strong); color: var(--ink-2); background: var(--surface); }
228
+ .icon-button:hover { border-color: #b9c4cc; color: var(--ink); background: var(--surface-sunken); }
229
+ .icon-button.danger-button { border-color: var(--danger-line); color: var(--danger); }
230
+ .icon-button.danger-button:hover { border-color: var(--danger); color: #fff; background: var(--danger); }
231
+
232
+ #back { margin-bottom: var(--s4); }
233
+
234
+ .toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin: 0 0 var(--s4); }
235
+ .toolbar > .pager { margin-left: auto; }
151
236
  .toolbar + h2 { margin-top: 0; }
152
- .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(265px, 1fr)); align-items: start; gap: 18px; }
153
- .grid > form, .grid > section, #view > form, #view > article {
154
- min-width: 0;
155
- border: 1px solid var(--line);
156
- border-radius: 10px;
157
- padding: 20px;
158
- background: var(--surface-muted);
159
- }
160
- .grid + .toolbar { margin-top: 20px; }
161
237
 
162
- form { display: grid; align-content: start; gap: 14px; }
163
- form > button { justify-self: start; margin-top: 4px; }
164
- label { display: grid; gap: 6px; color: #31414c; font-size: .875rem; font-weight: 700; }
238
+ form { display: grid; align-content: start; gap: var(--s4); }
239
+ form > button { justify-self: start; }
240
+ label { display: grid; gap: var(--s1); color: var(--ink-2); font-size: var(--fs-sm); font-weight: 600; }
165
241
  input:not([type="checkbox"]), select, textarea {
166
242
  width: 100%;
167
- min-height: 42px;
243
+ min-height: 40px;
244
+ padding: var(--s2) var(--s3);
168
245
  border: 1px solid var(--line-strong);
169
- border-radius: 7px;
170
- padding: 9px 11px;
246
+ border-radius: var(--r-md);
171
247
  color: var(--ink);
172
248
  font-weight: 450;
173
- background: #fff;
174
- box-shadow: inset 0 1px 2px rgb(21 33 43 / 4%);
249
+ background: var(--surface);
175
250
  }
176
- textarea { min-height: 180px; resize: vertical; font-family: "Cascadia Mono", Consolas, monospace; font-size: .85rem; line-height: 1.5; }
177
- input:not([type="checkbox"]):hover, select:hover, textarea:hover { border-color: #8ca4b1; }
251
+ input:not([type="checkbox"]):hover, select:hover, textarea:hover { border-color: #b3c0c9; }
252
+ textarea { min-height: 180px; resize: vertical; font-family: var(--font-mono); font-size: var(--fs-sm); line-height: 1.5; }
253
+ fieldset { margin: 0; padding: var(--s4); border: 1px solid var(--line); border-radius: var(--r-md); }
254
+ legend { padding: 0 var(--s2); color: var(--ink-2); font-weight: 650; font-size: var(--fs-sm); }
178
255
 
179
- .check {
180
- display: flex;
181
- align-items: center;
182
- gap: 10px;
183
- min-height: 30px;
184
- padding: 5px 7px;
185
- border: 1px solid transparent;
186
- border-radius: 6px;
187
- color: #283943;
188
- font-size: .9rem;
189
- font-weight: 600;
190
- cursor: pointer;
191
- }
192
- .check:hover { border-color: #c8dcda; background: #edf7f6; }
193
- .check input[type="checkbox"] {
194
- width: 17px;
195
- height: 17px;
196
- min-width: 17px;
197
- margin: 0;
198
- accent-color: var(--brand);
199
- cursor: pointer;
256
+ .check { display: flex; align-items: center; gap: var(--s3); min-height: 32px; padding: var(--s1) var(--s2); border-radius: var(--r-sm); font-size: var(--fs-base); font-weight: 550; cursor: pointer; }
257
+ .check:hover { background: var(--surface-hover); }
258
+ .check input[type="checkbox"] { width: 16px; height: 16px; min-width: 16px; margin: 0; accent-color: var(--brand); cursor: pointer; }
259
+
260
+ .form-help { display: block; color: var(--muted); font-size: var(--fs-xs); font-weight: 450; line-height: 1.45; }
261
+ .form-help code { padding: 1px 5px; border-radius: var(--r-sm); color: var(--brand-strong); background: var(--brand-soft); font-family: var(--font-mono); font-size: .95em; }
262
+ .muted { color: var(--muted); font-size: var(--fs-sm); }
263
+ .error { color: var(--danger); }
264
+
265
+ #notice { min-height: 0; }
266
+ #notice:not(:empty) { margin: 0; padding: var(--s3) var(--s4); border: 1px solid var(--brand-line); border-radius: var(--r-md); color: var(--brand-strong); background: var(--brand-soft); }
267
+ #notice .error { color: var(--danger); }
268
+ #notice:has(.error) { border-color: var(--danger-line); color: var(--danger); background: var(--danger-soft); }
269
+
270
+ .page-header { display: flex; align-items: end; justify-content: space-between; gap: var(--s4); margin: 0 0 var(--s5); padding-bottom: var(--s4); border-bottom: 1px solid var(--line); }
271
+ .page-header h2 { margin: 0; }
272
+ .eyebrow { margin: 0 0 var(--s1); color: var(--brand); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
273
+ .section-heading { display: flex; align-items: end; justify-content: space-between; gap: var(--s4); margin-bottom: var(--s3); }
274
+ .section-heading h3 { margin: 0; }
275
+
276
+ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); align-items: start; gap: var(--s4); }
277
+ .grid > form, .grid > section, #view > form, #view > article {
278
+ min-width: 0;
279
+ padding: var(--s4);
280
+ border: 1px solid var(--line);
281
+ border-radius: var(--r-md);
282
+ background: var(--surface-sunken);
200
283
  }
201
- .form-help { display: block; color: var(--muted); font-size: .8rem; font-weight: 450; line-height: 1.4; }
202
- .form-help code { padding: 1px 4px; border-radius: 3px; color: #245158; background: #e6f2f1; font-family: "Cascadia Mono", Consolas, monospace; font-size: .92em; }
203
-
204
- .role-menu-groups { display: grid; gap: 12px; }
205
- .role-menu-group { min-width: 0; margin: 0; overflow: hidden; border: 1px solid var(--line); border-radius: 10px; background: #fff; }
206
- .role-menu-group .menu-group-header > div:first-child strong, .role-menu-group .menu-group-header > div:first-child small { display: block; }
207
- .role-menu-group .menu-group-header > div:first-child strong { color: #263b47; font-size: .9rem; }
208
- .role-menu-group .menu-group-header > div:first-child small { margin-top: 2px; color: var(--muted); font-size: .75rem; }
284
+ .grid + .toolbar { margin-top: var(--s4); }
285
+
286
+ /* Tabelle */
287
+ table { width: 100%; margin-top: var(--s4); border: 1px solid var(--line); border-radius: var(--r-md); border-collapse: separate; border-spacing: 0; overflow: hidden; background: var(--surface); }
288
+ th, td { padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
289
+ th { color: var(--muted); font-size: var(--fs-xs); font-weight: 650; letter-spacing: .04em; text-transform: uppercase; background: var(--surface-sunken); }
290
+ td { font-size: var(--fs-base); }
291
+ tr:last-child td { border-bottom: 0; }
292
+ tbody tr:hover { background: var(--surface-hover); }
293
+ td:last-child, th:last-child { text-align: right; }
294
+ td button { min-height: 32px; padding: var(--s1) var(--s3); font-size: var(--fs-sm); }
295
+ table code, .entity-metadata dd, .brand small, .role-code { font-variant-numeric: tabular-nums; }
296
+
297
+ /* Metadati e chip */
298
+ .entity-metadata { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s2); margin: var(--s2) 0 0; }
299
+ .entity-metadata div { display: inline-flex; min-width: 0; max-width: 100%; overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface-sunken); }
300
+ .entity-metadata dt { flex: 0 0 auto; padding: 2px var(--s2); color: var(--muted); font-size: 11px; font-weight: 650; letter-spacing: .03em; text-transform: uppercase; background: var(--surface-hover); }
301
+ .entity-metadata dd { min-width: 0; margin: 0; padding: 2px var(--s2); overflow: hidden; color: var(--ink-2); font-family: var(--font-mono); font-size: var(--fs-xs); overflow-wrap: anywhere; }
302
+ .entity-note { margin: var(--s2) 0 0; color: var(--muted); font-size: var(--fs-xs); line-height: 1.45; }
303
+ .entity-note strong { margin-right: var(--s2); color: var(--ink-2); text-transform: uppercase; }
304
+ .is-disabled { opacity: .55; }
305
+
306
+ .status-label { display: inline-block; padding: 2px var(--s2); border: 1px solid; border-radius: var(--r-pill); font-size: var(--fs-xs); font-weight: 650; }
307
+ .status-enabled { border-color: var(--brand-line); color: var(--brand-strong); background: var(--brand-soft); }
308
+ .status-disabled { border-color: var(--warn-line); color: var(--warn-ink); background: var(--warn-soft); }
309
+ .permission-level { min-width: 84px; padding: var(--s1) var(--s2); border: 1px solid var(--brand-line); border-radius: var(--r-sm); color: var(--brand-strong); font-size: var(--fs-xs); font-weight: 650; text-align: center; background: var(--brand-soft); }
310
+
311
+ .role-kind, .group-kind, .menu-kind { display: inline-block; margin: 0 0 var(--s1); padding: 1px var(--s2); border-radius: var(--r-pill); font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
312
+ .role-kind { color: var(--brand-strong); background: var(--brand-soft); }
313
+ .group-kind { color: var(--warn-ink); background: var(--warn-soft); }
314
+ .menu-kind { color: var(--ink-2); background: var(--surface-sunken); }
315
+
316
+ /* Utente */
317
+ .user-editor { display: grid; gap: var(--s4); }
318
+ .user-editor > form, .user-editor > section, .user-editor-section { min-width: 0; margin: 0; padding: var(--s5); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-sunken); }
319
+ .user-editor-section > h3 { margin-bottom: var(--s2); }
320
+ .user-action-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s4); }
321
+ .user-action-bar #back { margin: 0; }
322
+ .user-tabs { display: flex; gap: var(--s1); margin: 0 0 var(--s4); padding: var(--s1); overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-sunken); }
323
+ .user-tabs button { flex: 0 0 auto; min-height: 34px; border: 0; color: var(--ink-2); background: transparent; }
324
+ .user-tabs button:hover { color: var(--ink); background: var(--surface); }
325
+ .user-tabs button[aria-selected="true"] { color: var(--brand-strong); background: var(--surface); box-shadow: var(--shadow-sm); }
326
+
327
+ /* Ruoli e grant */
328
+ .role-menu-groups { display: grid; gap: var(--s3); }
329
+ .role-menu-group { min-width: 0; margin: 0; padding: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
330
+ .role-menu-group .menu-group-header > div:first-child strong { display: block; color: var(--ink); font-size: var(--fs-sm); }
331
+ .role-menu-group .menu-group-header > div:first-child small { display: block; margin-top: 2px; color: var(--muted); font-size: var(--fs-xs); }
209
332
  .menu-item-content { min-width: 0; flex: 1; }
210
333
 
211
- .entity-metadata { display: flex; flex-wrap: wrap; gap: 5px 7px; margin: 7px 0 0; }
212
- .entity-metadata div { display: inline-flex; min-width: 0; max-width: 100%; overflow: hidden; border: 1px solid #dbe4e9; border-radius: 4px; background: #f7f9fb; }
213
- .entity-metadata dt { flex: 0 0 auto; padding: 2px 5px; color: #607080; font-size: .66rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; background: #edf2f5; }
214
- .entity-metadata dd { min-width: 0; margin: 0; padding: 2px 5px; overflow: hidden; color: #354854; font-family: "Cascadia Mono", Consolas, monospace; font-size: .7rem; font-weight: 500; overflow-wrap: anywhere; }
215
- .entity-note { margin: 6px 0 0; color: #52636e; font-size: .76rem; font-weight: 450; line-height: 1.4; }
216
- .entity-note strong { margin-right: 5px; color: #40545f; font-size: .7rem; text-transform: uppercase; }
217
- .is-disabled { opacity: .62; }
218
-
219
- .menu-group-list { display: grid; gap: 16px; margin-top: 16px; }
220
- .menu-group-card { margin: 0; overflow: hidden; border: 1px solid var(--line); border-radius: 10px; background: #fff; }
221
- .menu-group-header { display: grid; grid-template-columns: minmax(220px, 1fr) auto; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--line); background: #f4f7f9; }
222
- .menu-group-header > .check { padding: 2px 0; }
334
+ .role-assignment-list { display: grid; gap: var(--s3); }
335
+ .role-assignment-list .check span, .role-assignment-list .check small { display: block; }
336
+ .role-assignment-list .check small { margin-top: 2px; color: var(--muted); font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 500; }
337
+ .role-overview-list { display: grid; gap: var(--s3); margin-top: var(--s4); }
338
+ .role-assignment-card { margin: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
339
+ .role-assignment-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line); background: var(--surface-sunken); }
340
+ .role-assignment-heading .check { padding: 0; }
341
+ .role-menu-count { flex: 0 0 auto; padding: 2px var(--s2); border: 1px solid var(--line); border-radius: var(--r-pill); color: var(--ink-2); font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 650; background: var(--surface); }
342
+
343
+ /* Schede ruolo: intestazione con azioni in linea, menu assegnati su richiesta */
344
+ .role-card { overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
345
+ .role-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); padding: var(--s3) var(--s4); background: var(--surface-sunken); }
346
+ .role-card-title { min-width: 0; }
347
+ .role-card-title strong { display: block; color: var(--ink); font-size: var(--fs-md); }
348
+ .role-card-meta { display: block; margin-top: 2px; color: var(--muted); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
349
+ .role-card-actions { display: flex; flex: 0 0 auto; gap: var(--s2); }
350
+ .role-card-actions button { min-height: 34px; }
351
+ .role-card-empty { margin: 0; padding: var(--s3) var(--s4); color: var(--muted); font-size: var(--fs-sm); }
352
+ .role-card-menus { border-top: 1px solid var(--line); }
353
+ .role-card-menus > summary { padding: var(--s2) var(--s4); color: var(--ink-2); font-size: var(--fs-sm); font-weight: 600; cursor: pointer; list-style: none; }
354
+ .role-card-menus > summary::-webkit-details-marker { display: none; }
355
+ .role-card-menus > summary:hover { background: var(--surface-hover); }
356
+ .role-card-menus[open] > summary { border-bottom: 1px solid var(--line); }
357
+ /* Albero delle abilitazioni: gruppo -> menu -> livello */
358
+ .role-tree { margin: 0; padding: 0; list-style: none; }
359
+ .role-tree-group { border-bottom: 1px solid var(--line); }
360
+ .role-tree-group:last-child { border-bottom: 0; }
361
+ .role-tree-group.is-disabled > .role-tree-group-head strong { color: var(--muted); }
362
+ .role-tree-group.is-orphan > .role-tree-group-head strong { color: var(--warn-ink); }
363
+ .role-tree-group-head { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s4); background: var(--surface-sunken); }
364
+ .role-tree-group-head::before { content: ""; flex: 0 0 auto; width: 0; height: 0; border-left: 5px solid var(--muted); border-top: 4px solid transparent; border-bottom: 4px solid transparent; }
365
+ .role-tree-group-head strong { flex: 1 1 auto; min-width: 0; color: var(--ink-2); font-size: var(--fs-sm); }
366
+ .role-tree-count { flex: 0 0 auto; color: var(--muted); font-size: var(--fs-xs); font-variant-numeric: tabular-nums; }
367
+ .role-tree-menus { margin: 0 0 var(--s1) var(--s5); padding: 0 0 0 var(--s3); list-style: none; border-left: 1px solid var(--line); }
368
+ .role-tree-menu { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s3); padding: var(--s1) var(--s4) var(--s1) var(--s2); font-size: var(--fs-sm); }
369
+ .role-tree-menu::before { content: ""; position: absolute; top: 50%; left: calc(-1 * var(--s3)); width: var(--s3); height: 1px; background: var(--line); }
370
+ .role-tree-menu-name { min-width: 0; color: var(--ink); }
371
+ .role-tree-menu.is-disabled .role-tree-menu-name { color: var(--muted); }
372
+ .role-tree-menu .permission-level { min-width: 76px; }
373
+
374
+ /* Editor menu del ruolo: inclusione e livello, una riga per menu */
375
+ .role-menu-group-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line); background: var(--surface-sunken); }
376
+ .role-menu-group-head strong { color: var(--ink); font-size: var(--fs-sm); }
377
+ .role-menu-options { margin: 0; padding: 0; list-style: none; }
378
+ .role-menu-option { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); padding: var(--s1) var(--s3); border-bottom: 1px solid var(--line); }
379
+ .role-menu-option:last-child { border-bottom: 0; }
380
+ .role-menu-option.is-disabled { opacity: .55; }
381
+ .role-menu-option .check { flex: 1 1 auto; }
382
+ .role-menu-level { display: inline-flex; align-items: center; gap: var(--s2); flex: 0 0 auto; color: var(--muted); font-size: var(--fs-xs); }
383
+ .role-menu-level select { min-height: 32px; padding: var(--s1) var(--s2); font-size: var(--fs-sm); }
384
+ .role-menu-empty { padding: var(--s2) var(--s3); font-size: var(--fs-sm); }
385
+ .role-permission-groups { display: grid; gap: var(--s3); padding: var(--s3); }
386
+ .role-permission-group { overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-sm); }
387
+ .role-permission-group-heading { display: flex; align-items: start; justify-content: space-between; gap: var(--s3); padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line); color: var(--ink-2); background: var(--surface-sunken); }
388
+ .role-permission-group-heading strong { display: block; }
389
+ .role-permission-group-heading > .entity-metadata { justify-content: flex-end; margin: 0; }
390
+ .role-permission-entry { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s3); align-items: start; padding: var(--s3); border-bottom: 1px solid var(--line); }
391
+ .role-permission-entry:last-child { border-bottom: 0; }
392
+ .role-permission-entry > div > strong { display: block; color: var(--ink); }
393
+ .missing-role-menus { border-color: var(--warn-line); }
394
+ .missing-role-menus > strong { display: block; padding: var(--s2) var(--s3); color: var(--warn-ink); background: var(--warn-soft); }
395
+
396
+ .grant-menu-groups { display: grid; gap: var(--s3); }
397
+ .grant-menu-group { min-width: 0; margin: 0; padding: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
398
+ .grant-menu-group legend { width: 100%; padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line); color: var(--ink); font-size: var(--fs-base); font-weight: 650; background: var(--surface-sunken); }
399
+ .grant-menu-group > .entity-metadata { margin: 0; padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line); }
400
+ .grant-menu-options { display: grid; gap: var(--s2); padding: var(--s3); }
401
+ .grant-menu-option { display: grid; gap: var(--s2); padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); }
402
+ .grant-menu-info > strong { display: block; color: var(--ink); font-size: var(--fs-base); }
403
+ .grant-level { max-width: 260px; color: var(--ink-2); font-size: var(--fs-sm); }
404
+ .grant-level select { min-height: 36px; }
405
+
406
+ /* SSO */
407
+ .sso-identity-section { border-color: var(--brand-line); background: var(--surface); }
408
+ .sso-identity-list { display: grid; gap: var(--s2); margin: var(--s4) 0; }
409
+ .sso-identity-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s3); align-items: center; margin: 0; padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); }
410
+ .sso-identity-data > strong { display: block; color: var(--ink); font-family: var(--font-mono); font-size: var(--fs-sm); }
411
+ .sso-identity-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s2); }
412
+ .sso-link-form { margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--line); }
413
+
414
+ /* Menu e gruppi */
415
+ .menu-group-list { display: grid; gap: var(--s4); margin-top: var(--s4); }
416
+ .menu-group-card { margin: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
417
+ .menu-group-header { display: grid; grid-template-columns: minmax(220px, 1fr) auto; gap: var(--s3); padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line); background: var(--surface-sunken); }
418
+ .menu-group-header > .check { padding: 0; }
223
419
  .menu-group-header .check strong, .menu-group-header .check small { display: block; }
224
- .menu-group-header .check small { margin-top: 2px; color: var(--muted); font-size: .75rem; font-weight: 500; }
420
+ .menu-group-header .check small { margin-top: 2px; color: var(--muted); font-size: var(--fs-xs); font-weight: 500; }
225
421
  .menu-group-header > .entity-metadata { justify-content: flex-end; align-content: start; margin: 0; }
226
- .menu-group-items { display: grid; grid-template-columns: repeat(auto-fit, minmax(285px, 1fr)); gap: 6px; padding: 10px; }
227
- .menu-item { align-items: flex-start; min-height: 94px; padding: 9px; border-color: #e1e8ec; background: #fff; }
228
- .menu-item:hover { border-color: #b7d4d2; background: #f6fbfa; }
229
-
230
- .menu-table-wrap { overflow-x: auto; background: #fff; }
422
+ .menu-group-items { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--s2); padding: var(--s3); }
423
+ .menu-item { align-items: flex-start; min-height: 88px; padding: var(--s3); border: 1px solid var(--line); background: var(--surface); }
424
+ .menu-item:hover { border-color: var(--brand-line); background: var(--surface-hover); }
425
+ .menu-table-wrap { overflow-x: auto; background: var(--surface); }
231
426
  .menu-table { min-width: 1080px; margin: 0; border: 0; border-radius: 0; }
232
427
  .menu-table th, .menu-table td { white-space: normal; }
233
- .menu-table td { min-width: 86px; color: #354854; font-size: .82rem; }
428
+ .menu-table td { min-width: 86px; color: var(--ink-2); font-size: var(--fs-sm); }
234
429
  .menu-table td:nth-child(2) { min-width: 180px; color: var(--ink); }
235
430
  .menu-table td:nth-child(6), .menu-table td:nth-child(7), .menu-table td:nth-child(8) { min-width: 150px; overflow-wrap: anywhere; }
236
- .menu-table td:last-child { text-align: left; }
237
- .menu-table code { color: #245158; font-family: "Cascadia Mono", Consolas, monospace; font-size: .76rem; overflow-wrap: anywhere; }
238
- .table-toggle { display: inline-flex; align-items: center; gap: 7px; color: #40545f; font-size: .78rem; font-weight: 650; }
431
+ .menu-table code { color: var(--brand-strong); font-family: var(--font-mono); font-size: var(--fs-xs); overflow-wrap: anywhere; }
432
+ .table-toggle { display: inline-flex; align-items: center; gap: var(--s2); color: var(--ink-2); font-size: var(--fs-sm); font-weight: 600; }
433
+ .table-toggle input { width: 16px; height: 16px; margin: 0; accent-color: var(--brand); }
239
434
  .role-menu-table { min-width: 1420px; }
240
435
  .role-menu-table th, .role-menu-table td { white-space: nowrap; }
241
436
  .role-menu-table td:nth-child(2) { min-width: 220px; white-space: normal; }
242
437
  .role-menu-table td:nth-child(6), .role-menu-table td:nth-child(7), .role-menu-table td:nth-child(10) { min-width: 155px; white-space: normal; overflow-wrap: anywhere; }
243
438
  .role-menu-table td:nth-child(9) { min-width: 145px; }
244
- .role-menu-table td:last-child { text-align: left; }
245
439
  .table-select { display: block; }
246
- .table-select select { min-height: 34px; padding: 5px 28px 5px 8px; font-size: .8rem; }
247
- .status-label { display: inline-block; padding: 3px 7px; border: 1px solid; border-radius: 999px; font-size: .72rem; font-weight: 700; }
248
- .status-enabled { border-color: #add7cd; color: #155b4b; background: #eef8f4; }
249
- .status-disabled { border-color: #d7c9ad; color: #735a27; background: #fbf7ed; }
250
- .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
251
- .table-toggle input { width: 16px; height: 16px; margin: 0; accent-color: var(--brand); }
440
+ .table-select select { min-height: 34px; padding: var(--s1) var(--s3); font-size: var(--fs-sm); }
252
441
 
253
- .user-editor { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; }
254
- .user-editor > form, .user-editor > section, .user-editor-section { min-width: 0; margin: 0; border: 1px solid var(--line); border-radius: 10px; padding: 20px; background: var(--surface-muted); }
255
- .user-editor-section > h3 { margin-bottom: 8px; }
256
- .user-action-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
257
- .user-action-bar #back { margin: 0; }
258
- .user-tabs { display: flex; gap: 4px; margin: 0 0 18px; padding: 5px; overflow-x: auto; border: 1px solid var(--line); border-radius: 9px; background: #f4f7f9; }
259
- .user-tabs button { flex: 0 0 auto; min-height: 36px; border-color: transparent; color: #40525c; background: transparent; box-shadow: none; }
260
- .user-tabs button:hover, .user-tabs button[aria-selected="true"] { color: #fff; background: var(--brand); }
261
- .role-assignment-list { display: grid; gap: 5px; }
262
- .role-assignment-list .check span, .role-assignment-list .check small { display: block; }
263
- .role-assignment-list .check small { margin-top: 2px; color: var(--muted); font-family: "Cascadia Mono", Consolas, monospace; font-size: .72rem; font-weight: 500; }
264
- .role-assignment-list { gap: 14px; }
265
- .role-overview-list { display: grid; gap: 14px; margin-top: 16px; }
266
- .role-assignment-card { margin: 0; overflow: hidden; border: 1px solid var(--line); border-radius: 8px; background: #fff; }
267
- .role-assignment-heading { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 11px 13px; border-bottom: 1px solid var(--line); background: #f4f7f9; }
268
- .role-assignment-heading .check { padding: 0; }
269
- .role-assignment-heading .check strong { color: #263b47; }
270
- .role-overview-card { position: relative; border-color: #a9cecb; box-shadow: 0 5px 16px rgb(13 92 99 / 7%); }
271
- .role-overview-details { min-width: 0; }
272
- .role-overview-details > summary { min-height: 76px; padding-right: 122px; list-style: none; cursor: pointer; border-bottom: 0; color: #fff; background: linear-gradient(120deg, var(--brand-strong), var(--brand)); }
273
- .role-overview-details > summary::-webkit-details-marker { display: none; }
274
- .role-overview-details > summary:hover { background: linear-gradient(120deg, #063c41, #0c6971); }
275
- .role-overview-details[open] > summary { border-bottom: 1px solid #b6d8d5; }
276
- .role-identity > strong, .role-code { display: block; }
277
- .role-identity > strong { color: #fff; font-size: 1.02rem; }
278
- .role-code { margin-top: 2px; color: var(--muted); font-family: "Cascadia Mono", Consolas, monospace; font-size: .72rem; font-weight: 500; }
279
- .role-overview-details .role-code { color: #d0e8e6; }
280
- .role-overview-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 7px; }
281
- .role-menu-count { flex: 0 0 auto; padding: 3px 7px; border: 1px solid #c9dddb; border-radius: 99px; color: #245158; font-family: "Cascadia Mono", Consolas, monospace; font-size: .72rem; font-weight: 700; background: #eff8f7; }
282
- .role-overview-details .role-menu-count { border-color: rgb(255 255 255 / 38%); color: #fff; background: rgb(255 255 255 / 14%); }
283
- .role-expand-hint { color: #d0e8e6; font-size: .77rem; font-weight: 650; }
284
- .role-overview-details[open] .when-closed, .role-overview-details:not([open]) .when-open { display: none; }
285
- .role-edit-button { position: absolute; top: 20px; right: 13px; min-height: 34px; padding: 5px 10px; border-color: #fff; color: var(--brand-strong); background: #fff; font-size: .82rem; }
286
- .role-edit-button:hover { border-color: #d4ece9; color: #fff; background: transparent; }
287
- .role-kind, .group-kind, .menu-kind { display: inline-block; margin: 0 0 3px; border-radius: 999px; font-size: .63rem; font-weight: 800; letter-spacing: .075em; line-height: 1.3; text-transform: uppercase; }
288
- .role-kind { padding: 2px 6px; color: #0a4e54; background: #d8f0ed; }
289
- .group-kind { padding: 2px 6px; color: #5a4818; background: #f4ebc6; }
290
- .menu-kind { padding: 2px 6px; color: #4c5b67; background: #e7edf1; }
291
- .role-permission-groups { display: grid; gap: 10px; padding: 10px; }
292
- .role-permission-group { overflow: hidden; border: 1px solid #ddd5b6; border-radius: 7px; }
293
- .role-permission-group-heading { display: flex; align-items: start; justify-content: space-between; gap: 12px; padding: 9px 10px; border-bottom: 1px solid #ddd5b6; color: #51451f; background: #fffcf1; }
294
- .role-permission-group-heading strong { display: block; }
295
- .role-permission-group-heading > .entity-metadata { justify-content: flex-end; margin: 0; }
296
- .role-permission-entry { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: start; padding: 10px; border-bottom: 1px solid #e8eef1; background: #fff; }
297
- .role-permission-entry:last-child { border-bottom: 0; }
298
- .role-permission-entry > div > strong { display: block; color: #283943; }
299
- .permission-level { min-width: 88px; padding: 4px 7px; border: 1px solid #b9d9d7; border-radius: 5px; color: #15515a; font-size: .75rem; font-weight: 750; text-align: center; background: #edf7f6; }
300
- .missing-role-menus { border-color: #edcfad; }
301
- .missing-role-menus > strong { display: block; padding: 8px 10px; color: #7a4d17; background: #fff8ed; }
302
-
303
- .grant-menu-groups { display: grid; gap: 14px; }
304
- .grant-menu-group { min-width: 0; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: 8px; background: #fff; overflow: hidden; }
305
- .grant-menu-group legend { width: 100%; box-sizing: border-box; padding: 10px 13px; border-bottom: 1px solid var(--line); color: #263b47; background: #f4f7f9; font-size: .92rem; font-weight: 750; }
306
- .grant-menu-group > .entity-metadata { padding: 9px 12px; margin: 0; border-bottom: 1px solid var(--line); background: #fafcfd; }
307
- .grant-menu-options { display: grid; gap: 8px; padding: 10px; }
308
- .grant-menu-option { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; padding: 12px; border: 1px solid #dfe7eb; border-radius: 7px; background: #fff; }
309
- .grant-menu-info > strong { display: block; color: #283943; font-size: .95rem; line-height: 1.35; }
310
- .grant-level { max-width: 260px; color: #40545f; font-size: .78rem; }
311
- .grant-level select { min-height: 38px; }
312
-
313
- .section-heading { display: flex; align-items: end; justify-content: space-between; gap: 16px; margin-bottom: 8px; }
314
- .section-heading h3 { margin: 0; }
315
- .sso-identity-section { border-color: #b9d9d7; background: linear-gradient(135deg, #f3fbfa, var(--surface-muted) 58%); }
316
- .sso-identity-list { display: grid; gap: 8px; margin: 14px 0; }
317
- .sso-identity-item { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 14px; align-items: center; margin: 0; padding: 12px; border: 1px solid #cfe1e0; border-radius: 8px; background: #fff; }
318
- .sso-identity-data > strong { display: block; color: #1b4d53; font-family: "Cascadia Mono", Consolas, monospace; font-size: .9rem; }
319
- .sso-identity-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 7px; }
320
- .icon-button { display: inline-grid; place-items: center; width: 38px; min-width: 38px; min-height: 38px; padding: 0; font-size: 1.1rem; line-height: 1; }
321
- .danger-button { border-color: #dca39d; color: var(--danger); background: #fff7f6; }
322
- .danger-button:hover { border-color: var(--danger); color: #fff; background: var(--danger); box-shadow: 0 4px 10px rgb(180 35 24 / 18%); }
323
- .sso-link-form { margin-top: 18px; padding-top: 16px; border-top: 1px solid #cfe1e0; }
324
-
325
- table { width: 100%; margin-top: 16px; border: 1px solid var(--line); border-radius: 9px; border-collapse: separate; border-spacing: 0; overflow: hidden; background: #fff; }
326
- th, td { padding: 12px 14px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
327
- th { color: #52636e; font-size: .74rem; font-weight: 750; letter-spacing: .06em; text-transform: uppercase; background: #f4f7f9; }
328
- tr:last-child td { border-bottom: 0; }
329
- tbody tr:hover { background: #f7fbfb; }
330
- td:last-child { text-align: right; }
331
- td button { min-height: 32px; padding: 5px 10px; font-size: .85rem; }
332
-
333
- article { margin-top: 14px; }
334
- article h3 { margin-bottom: 8px; }
335
- article .check { margin-left: 10px; }
336
- .menu-group-card .check { margin-left: 0; }
337
- .grid > section > p:not(.form-help) { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line); }
442
+ article { margin-top: var(--s4); }
443
+ article h3 { margin-bottom: var(--s2); }
444
+ .grid > section > p:not(.form-help) { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); padding: var(--s2) 0; border-bottom: 1px solid var(--line); }
338
445
  .grid > section > p:not(.form-help):last-of-type { border-bottom: 0; }
339
446
  .grid > section > p:not(.form-help) button { flex: 0 0 auto; }
340
- .muted { color: var(--muted); font-size: .9rem; }
341
- .error { color: var(--danger); }
342
447
 
343
- @media (max-width: 760px) {
344
- #app { padding: 14px; }
345
- .card { margin: 6vh auto; padding: 24px; }
346
- header { min-height: 74px; padding: 14px; border-radius: 10px; }
347
- #view { min-height: 0; padding: 18px; border-radius: 10px; }
348
- .page-header { display: block; margin-bottom: 18px; }
349
- .grid { grid-template-columns: 1fr; }
448
+ /* Token di servizio */
449
+ .token-reveal { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s3); margin: var(--s4) 0; padding: var(--s4); border: 1px solid var(--brand-line); border-radius: var(--r-md); background: var(--brand-soft); }
450
+ .token-reveal code { flex: 1 1 100%; word-break: break-all; color: var(--brand-strong); font-family: var(--font-mono); font-size: var(--fs-sm); }
451
+ .token-reveal button { flex: 0 0 auto; }
452
+
453
+ /* Paginatore — contenitore dedicato sopra/sotto la tabella, sempre orizzontale */
454
+ .pager-row { display: flex; justify-content: flex-end; }
455
+ .pager-row-top { margin: 0 0 var(--s3); }
456
+ .pager-row-bottom { margin-top: var(--s4); }
457
+
458
+ .pager { display: inline-flex; flex-direction: row; flex-wrap: nowrap; align-items: center; gap: var(--s3); white-space: nowrap; }
459
+ .pager-controls { display: inline-flex; flex-direction: row; flex-wrap: nowrap; align-items: center; gap: var(--s1); }
460
+ .pager-item {
461
+ display: inline-flex;
462
+ align-items: center;
463
+ justify-content: center;
464
+ min-width: 34px;
465
+ height: 34px;
466
+ padding: 0 var(--s2);
467
+ border: 1px solid var(--line-strong);
468
+ border-radius: var(--r-sm);
469
+ color: var(--ink-2);
470
+ font-size: var(--fs-sm);
471
+ font-weight: 600;
472
+ line-height: 1;
473
+ font-variant-numeric: tabular-nums;
474
+ background: var(--surface);
475
+ }
476
+ .pager-item:hover:not(:disabled):not([aria-current="page"]) { border-color: #b9c4cc; color: var(--ink); background: var(--surface-sunken); }
477
+ .pager-item[aria-current="page"] { border-color: var(--brand); color: #fff; background: var(--brand); cursor: default; }
478
+ .pager-item:disabled { opacity: .45; }
479
+ .pager-nav { font-size: var(--fs-lg); }
480
+ .pager-gap { display: inline-flex; align-items: center; justify-content: center; min-width: 24px; color: var(--muted); }
481
+ .pager-context { color: var(--muted); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
482
+ #notice:empty { display: none; }
483
+
484
+ /* Ruoli in tabella: etichette con espansione "altre N" */
485
+ .roles-col { max-width: 320px; white-space: normal; }
486
+ .roles-cell { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--s1) var(--s2); }
487
+ .roles-list { min-width: 0; }
488
+ .link-button {
489
+ min-height: 0;
490
+ padding: 0;
491
+ border: 0;
492
+ color: var(--brand);
493
+ font-weight: 600;
494
+ text-decoration: underline;
495
+ background: none;
496
+ }
497
+ .link-button:hover { color: var(--brand-strong); background: none; box-shadow: none; }
498
+
499
+ /* Azioni di gestione: pulsanti compatti nelle tabelle catalogo e nelle card */
500
+ .row-actions { display: flex; flex-wrap: wrap; gap: var(--s1); justify-content: flex-end; }
501
+ .row-actions button { min-height: 30px; padding: 0 var(--s2); font-size: var(--fs-xs); }
502
+ .menu-group-actions { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--s2); justify-content: flex-end; }
503
+ .inline-field { display: inline-flex; align-items: center; gap: var(--s2); color: var(--muted); font-size: var(--fs-sm); }
504
+ .inline-field select { min-height: 34px; }
505
+
506
+ /* ---------------------------------------------------------------- wiki */
507
+ .wiki { display: grid; grid-template-columns: minmax(220px, 260px) minmax(0, 1fr); gap: var(--s5); align-items: start; }
508
+ .wiki-index { position: sticky; top: var(--s4); max-height: calc(100vh - 2 * var(--s4)); overflow-y: auto; padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-sunken); }
509
+ .wiki-index-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s3); }
510
+ .wiki-index-head strong { color: var(--ink); font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: .06em; }
511
+ .wiki-index-head button { min-height: 30px; padding: 0 var(--s2); font-size: var(--fs-xs); }
512
+ .wiki-index-group { margin-bottom: var(--s3); }
513
+ .wiki-index-group-title { display: block; margin-bottom: var(--s1); color: var(--muted); font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
514
+ .wiki-index ul { display: grid; gap: 1px; margin: 0; padding: 0; list-style: none; }
515
+ .wiki-index a { display: block; padding: var(--s1) var(--s2); border-radius: var(--r-sm); color: var(--ink-2); font-size: var(--fs-sm); text-decoration: none; }
516
+ .wiki-index a:hover { color: var(--ink); background: var(--surface-hover); }
517
+ .wiki-index a[aria-current="page"] { color: var(--brand-strong); background: var(--brand-soft); font-weight: 650; }
518
+
519
+ .wiki-content { display: grid; gap: var(--s3); min-width: 0; }
520
+ .wiki-section-head { padding-bottom: var(--s3); border-bottom: 2px solid var(--brand-line); }
521
+ .wiki-section-head h2 { margin: 0 0 var(--s1); }
522
+ .wiki-section-head p { margin: 0; color: var(--muted); }
523
+ .wiki-content > h3 { margin: var(--s4) 0 0; color: var(--ink); }
524
+ .wiki-content p { margin: 0; line-height: 1.6; }
525
+ .wiki-content ul, .wiki-content ol { display: grid; gap: var(--s1); margin: 0; padding-left: var(--s5); }
526
+ .wiki-content li { line-height: 1.55; }
527
+
528
+ .wiki-code { margin: 0; overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
529
+ .wiki-code.is-good { border-color: #2f9e6b; }
530
+ .wiki-code.is-bad { border-color: var(--danger-line); }
531
+ .wiki-code-head { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line); background: var(--surface-sunken); }
532
+ .wiki-code-title { flex: 1 1 auto; min-width: 0; color: var(--ink-2); font-size: var(--fs-xs); font-weight: 650; }
533
+ .wiki-code.is-good .wiki-code-title::before { content: "\2713 "; color: #2f9e6b; }
534
+ .wiki-code.is-bad .wiki-code-title::before { content: "\2717 "; color: var(--danger); }
535
+ .wiki-code-lang { color: var(--muted); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; }
536
+ .wiki-copy { min-height: 28px; padding: 0 var(--s2); font-size: var(--fs-xs); }
537
+ .wiki-code pre { margin: 0; padding: var(--s4); overflow-x: auto; }
538
+ .wiki-code code { color: var(--ink); font-family: var(--font-mono); font-size: var(--fs-sm); line-height: 1.55; white-space: pre; }
539
+
540
+ .wiki-callout { display: grid; gap: var(--s1); padding: var(--s3) var(--s4); border: 1px solid var(--line); border-left-width: 4px; border-radius: var(--r-sm); background: var(--surface); }
541
+ .wiki-callout strong { font-size: var(--fs-sm); }
542
+ .wiki-callout p { margin: 0; font-size: var(--fs-sm); }
543
+ .wiki-callout.is-info { border-left-color: var(--brand); background: var(--brand-soft); }
544
+ .wiki-callout.is-ok { border-left-color: #2f9e6b; background: #e8f6ee; }
545
+ .wiki-callout.is-warn { border-left-color: var(--warn-line); background: var(--warn-soft); }
546
+ .wiki-callout.is-danger { border-left-color: var(--danger); background: var(--danger-soft); }
547
+
548
+ .wiki-table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r-md); }
549
+ .wiki-table-wrap table { min-width: 520px; margin: 0; }
550
+ .wiki-table-wrap th { position: sticky; top: 0; }
551
+
552
+ @media (max-width: 900px) {
553
+ .wiki { grid-template-columns: 1fr; }
554
+ .wiki-index { position: static; max-height: none; }
555
+ }
556
+
557
+ /* Aiuto contestuale: icona "i" e popover con la miniguida del campo */
558
+ .help-dot { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; min-height: 0; margin-left: var(--s1); padding: 0; border: 1px solid var(--line-strong); border-radius: 50%; color: var(--muted); font-size: 11px; font-weight: 700; line-height: 1; background: var(--surface); vertical-align: middle; cursor: pointer; }
559
+ .help-dot:hover, .help-dot:focus-visible { color: var(--brand-strong); border-color: var(--brand-line); background: var(--brand-soft); }
560
+ .help-popover { position: fixed; z-index: 3000; width: min(460px, 94vw); max-height: 72vh; overflow: auto; padding: var(--s4); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); box-shadow: var(--shadow-md); }
561
+ .help-popover-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s3); }
562
+ .help-popover-head h4 { margin: 0; color: var(--ink); font-size: var(--fs-md); }
563
+ .help-close { width: 28px; min-height: 28px; padding: 0; font-size: var(--fs-lg); line-height: 1; }
564
+ .help-popover-body { display: grid; gap: var(--s3); }
565
+ .help-popover-body p { margin: 0; font-size: var(--fs-sm); line-height: 1.55; }
566
+ .help-popover-body ul, .help-popover-body ol { display: grid; gap: var(--s1); margin: 0; padding-left: var(--s4); font-size: var(--fs-sm); }
567
+ .help-popover-body h3 { margin: 0; font-size: var(--fs-base); }
568
+ .help-popover-body .wiki-table-wrap table { min-width: 0; }
569
+ .help-popover-body .wiki-code pre { padding: var(--s3); }
570
+
571
+ /* Feedback di caricamento */
572
+ #loading-overlay { position: fixed; z-index: 1000; inset: 0; display: grid; place-items: center; padding: var(--s5); background: rgb(12 28 39 / 28%); backdrop-filter: blur(2px); }
573
+ .loading-panel { display: flex; align-items: center; gap: var(--s4); width: min(100%, 340px); padding: var(--s4) var(--s5); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--shadow-md); }
574
+ .loading-panel strong, .loading-panel small { display: block; }
575
+ .loading-panel small { margin-top: 2px; color: var(--muted); }
576
+ .loading-spinner { width: 24px; height: 24px; flex: 0 0 24px; border: 3px solid var(--brand-line); border-top-color: var(--brand); border-radius: 50%; animation: accessi-spin .75s linear infinite; }
577
+ @keyframes accessi-spin { to { transform: rotate(360deg); } }
578
+
579
+ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
580
+
581
+ /* ---------------------------------------------------------------- responsive */
582
+
583
+ @media (max-width: 1024px) {
584
+ #console { grid-template-columns: 1fr; }
585
+ .sidebar { position: static; flex-direction: row; flex-wrap: wrap; align-items: center; }
586
+ .brand { flex: 1 1 auto; }
587
+ .sidebar nav { flex: 1 1 100%; }
588
+ .sidebar-logout { margin: 0; }
589
+ }
590
+
591
+ @media (max-width: 720px) {
592
+ #app { padding: var(--s4); }
593
+ .card { margin: 5vh auto; padding: var(--s5); }
594
+ #view { min-height: 0; padding: var(--s4); }
595
+ .page-header { display: block; }
596
+ .grid, .user-editor, .menu-group-items { grid-template-columns: 1fr; }
350
597
  .menu-group-header { grid-template-columns: 1fr; }
351
598
  .menu-group-header > .entity-metadata { justify-content: flex-start; }
352
- .menu-group-items { grid-template-columns: 1fr; }
353
- .user-editor-section { padding: 16px; }
354
- .user-action-bar { align-items: stretch; }
355
- .user-action-bar button { flex: 1; }
599
+ .user-editor-section { padding: var(--s4); }
600
+ .user-action-bar { flex-direction: column; align-items: stretch; }
601
+ .user-action-bar button { width: 100%; }
356
602
  .grant-level { max-width: none; }
357
603
  .section-heading, .sso-identity-item { grid-template-columns: 1fr; align-items: start; }
358
604
  .section-heading { display: grid; }
359
605
  .sso-identity-actions { justify-content: flex-start; }
360
606
  .role-assignment-heading, .role-permission-group-heading, .role-permission-entry { display: grid; grid-template-columns: 1fr; }
361
- .role-overview-actions { justify-content: flex-start; }
362
607
  .role-permission-group-heading > .entity-metadata { justify-content: flex-start; }
608
+ .role-card-head { flex-direction: column; align-items: stretch; }
609
+ .role-card-actions { justify-content: flex-start; }
610
+ .role-tree-menu { grid-template-columns: 1fr; }
363
611
  .permission-level { justify-self: start; }
364
612
  table { display: block; overflow-x: auto; white-space: nowrap; }
365
613
  .menu-table { display: table; }