wxcli 1.2.0__py3-none-any.whl

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 (413) hide show
  1. wxcli/__init__.py +4 -0
  2. wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
  3. wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
  4. wxcli/_playbook/.claude/rules/cleanup.md +29 -0
  5. wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
  6. wxcli/_playbook/.claude/rules/org-health.md +14 -0
  7. wxcli/_playbook/.claude/settings.json +8 -0
  8. wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
  9. wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
  10. wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
  11. wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
  12. wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
  13. wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
  14. wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
  15. wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
  16. wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
  17. wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
  18. wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
  19. wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
  20. wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
  21. wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
  22. wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
  23. wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
  24. wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
  25. wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
  26. wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
  27. wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
  28. wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
  29. wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
  30. wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
  31. wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
  32. wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
  33. wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
  34. wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
  35. wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
  36. wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
  37. wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
  38. wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
  39. wxcli/_playbook/CLAUDE.md +373 -0
  40. wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
  41. wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
  42. wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
  43. wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
  44. wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
  45. wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
  46. wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
  47. wxcli/_playbook/docs/reference/admin-partner.md +357 -0
  48. wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
  49. wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
  50. wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
  51. wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
  52. wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
  53. wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
  54. wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
  55. wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
  56. wxcli/_playbook/docs/reference/authentication.md +965 -0
  57. wxcli/_playbook/docs/reference/call-control.md +1205 -0
  58. wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
  59. wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
  60. wxcli/_playbook/docs/reference/call-routing.md +2304 -0
  61. wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
  62. wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
  63. wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
  64. wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
  65. wxcli/_playbook/docs/reference/devices-core.md +1869 -0
  66. wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
  67. wxcli/_playbook/docs/reference/devices-platform.md +467 -0
  68. wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
  69. wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
  70. wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
  71. wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
  72. wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
  73. wxcli/_playbook/docs/reference/meetings-content.md +473 -0
  74. wxcli/_playbook/docs/reference/meetings-core.md +903 -0
  75. wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
  76. wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
  77. wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
  78. wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
  79. wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
  80. wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
  81. wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
  82. wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
  83. wxcli/_playbook/docs/reference/provisioning.md +1366 -0
  84. wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
  85. wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
  86. wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
  87. wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
  88. wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
  89. wxcli/_version.py +24 -0
  90. wxcli/auth.py +137 -0
  91. wxcli/commands/__init__.py +0 -0
  92. wxcli/commands/_registry.py +181 -0
  93. wxcli/commands/activation_email.py +103 -0
  94. wxcli/commands/admin_recordings.py +585 -0
  95. wxcli/commands/analytics.py +105 -0
  96. wxcli/commands/announcement_playlists.py +219 -0
  97. wxcli/commands/announcements.py +519 -0
  98. wxcli/commands/archive_users.py +36 -0
  99. wxcli/commands/attachment_actions.py +60 -0
  100. wxcli/commands/audit_events.py +83 -0
  101. wxcli/commands/authorizations.py +113 -0
  102. wxcli/commands/auto_attendant.py +642 -0
  103. wxcli/commands/broadworks_billing_reports.py +126 -0
  104. wxcli/commands/broadworks_enterprises.py +160 -0
  105. wxcli/commands/broadworks_subscribers.py +319 -0
  106. wxcli/commands/broadworks_workspaces.py +108 -0
  107. wxcli/commands/call_controls.py +1304 -0
  108. wxcli/commands/call_park.py +494 -0
  109. wxcli/commands/call_pickup.py +229 -0
  110. wxcli/commands/call_queue.py +1878 -0
  111. wxcli/commands/call_recording.py +707 -0
  112. wxcli/commands/call_routing.py +1610 -0
  113. wxcli/commands/call_settings_for_me_phase_5.py +212 -0
  114. wxcli/commands/caller_reputation.py +169 -0
  115. wxcli/commands/calling_service.py +305 -0
  116. wxcli/commands/cc_address_book.py +770 -0
  117. wxcli/commands/cc_agent_greetings.py +242 -0
  118. wxcli/commands/cc_agent_summaries.py +39 -0
  119. wxcli/commands/cc_agent_wellbeing.py +216 -0
  120. wxcli/commands/cc_agents.py +425 -0
  121. wxcli/commands/cc_ai_assistant.py +55 -0
  122. wxcli/commands/cc_ai_feature.py +294 -0
  123. wxcli/commands/cc_audio_files.py +149 -0
  124. wxcli/commands/cc_auto_csat.py +311 -0
  125. wxcli/commands/cc_aux_code.py +458 -0
  126. wxcli/commands/cc_business_hour.py +353 -0
  127. wxcli/commands/cc_call_monitoring.py +228 -0
  128. wxcli/commands/cc_callbacks.py +194 -0
  129. wxcli/commands/cc_campaign.py +212 -0
  130. wxcli/commands/cc_captures.py +39 -0
  131. wxcli/commands/cc_contact_list.py +169 -0
  132. wxcli/commands/cc_contact_number.py +295 -0
  133. wxcli/commands/cc_data_sources.py +235 -0
  134. wxcli/commands/cc_desktop_layout.py +380 -0
  135. wxcli/commands/cc_desktop_profile.py +322 -0
  136. wxcli/commands/cc_dial_number.py +511 -0
  137. wxcli/commands/cc_dial_plan.py +347 -0
  138. wxcli/commands/cc_dnc.py +101 -0
  139. wxcli/commands/cc_entry_point.py +545 -0
  140. wxcli/commands/cc_ewt.py +51 -0
  141. wxcli/commands/cc_flow.py +477 -0
  142. wxcli/commands/cc_global_vars.py +430 -0
  143. wxcli/commands/cc_holiday_list.py +335 -0
  144. wxcli/commands/cc_journey.py +1261 -0
  145. wxcli/commands/cc_legacy_flows.py +49 -0
  146. wxcli/commands/cc_multimedia_profile.py +436 -0
  147. wxcli/commands/cc_notification.py +51 -0
  148. wxcli/commands/cc_outdial_ani.py +604 -0
  149. wxcli/commands/cc_overrides.py +341 -0
  150. wxcli/commands/cc_queue.py +1083 -0
  151. wxcli/commands/cc_queue_stats.py +55 -0
  152. wxcli/commands/cc_realtime.py +51 -0
  153. wxcli/commands/cc_resource_collection.py +312 -0
  154. wxcli/commands/cc_search.py +46 -0
  155. wxcli/commands/cc_site.py +400 -0
  156. wxcli/commands/cc_skill.py +350 -0
  157. wxcli/commands/cc_skill_profile.py +289 -0
  158. wxcli/commands/cc_subscriptions.py +426 -0
  159. wxcli/commands/cc_summaries.py +130 -0
  160. wxcli/commands/cc_tasks.py +844 -0
  161. wxcli/commands/cc_team.py +325 -0
  162. wxcli/commands/cc_user_profiles.py +349 -0
  163. wxcli/commands/cc_users.py +701 -0
  164. wxcli/commands/cc_work_types.py +363 -0
  165. wxcli/commands/cdr.py +89 -0
  166. wxcli/commands/classifications.py +38 -0
  167. wxcli/commands/cleanup.py +1427 -0
  168. wxcli/commands/client_settings.py +72 -0
  169. wxcli/commands/conference.py +328 -0
  170. wxcli/commands/configure.py +72 -0
  171. wxcli/commands/converged_recordings.py +347 -0
  172. wxcli/commands/converged_recordings_export.py +310 -0
  173. wxcli/commands/cq_playlists.py +42 -0
  174. wxcli/commands/cucm.py +2794 -0
  175. wxcli/commands/cucm_config.py +129 -0
  176. wxcli/commands/customer_assist.py +373 -0
  177. wxcli/commands/data_sources.py +227 -0
  178. wxcli/commands/dect_devices.py +787 -0
  179. wxcli/commands/device_configurations.py +77 -0
  180. wxcli/commands/device_dynamic_settings.py +320 -0
  181. wxcli/commands/device_settings.py +1489 -0
  182. wxcli/commands/devices.py +280 -0
  183. wxcli/commands/domains.py +142 -0
  184. wxcli/commands/ecm.py +178 -0
  185. wxcli/commands/emergency_services.py +827 -0
  186. wxcli/commands/events.py +83 -0
  187. wxcli/commands/external_voicemail.py +52 -0
  188. wxcli/commands/groups.py +206 -0
  189. wxcli/commands/guest_management.py +76 -0
  190. wxcli/commands/hds.py +340 -0
  191. wxcli/commands/hot_desk.py +67 -0
  192. wxcli/commands/hot_desking_members.py +118 -0
  193. wxcli/commands/hot_desking_portal.py +124 -0
  194. wxcli/commands/hunt_group.py +577 -0
  195. wxcli/commands/hybrid_clusters.py +71 -0
  196. wxcli/commands/hybrid_connectors.py +67 -0
  197. wxcli/commands/identity_org.py +159 -0
  198. wxcli/commands/init_playbook.py +155 -0
  199. wxcli/commands/licenses.py +106 -0
  200. wxcli/commands/live_monitoring.py +40 -0
  201. wxcli/commands/location_call_handling.py +577 -0
  202. wxcli/commands/location_schedules.py +341 -0
  203. wxcli/commands/location_settings.py +1297 -0
  204. wxcli/commands/location_voicemail.py +494 -0
  205. wxcli/commands/locations.py +336 -0
  206. wxcli/commands/meeting_captions.py +110 -0
  207. wxcli/commands/meeting_chats.py +63 -0
  208. wxcli/commands/meeting_invitees.py +234 -0
  209. wxcli/commands/meeting_messages.py +28 -0
  210. wxcli/commands/meeting_participants.py +278 -0
  211. wxcli/commands/meeting_polls.py +111 -0
  212. wxcli/commands/meeting_preferences.py +515 -0
  213. wxcli/commands/meeting_qa.py +78 -0
  214. wxcli/commands/meeting_qualities.py +43 -0
  215. wxcli/commands/meeting_reports.py +101 -0
  216. wxcli/commands/meeting_session_types.py +105 -0
  217. wxcli/commands/meeting_site.py +57 -0
  218. wxcli/commands/meeting_slido.py +44 -0
  219. wxcli/commands/meeting_summaries.py +92 -0
  220. wxcli/commands/meeting_tracking_codes.py +233 -0
  221. wxcli/commands/meeting_transcripts.py +230 -0
  222. wxcli/commands/meetings.py +1997 -0
  223. wxcli/commands/memberships.py +164 -0
  224. wxcli/commands/messages.py +213 -0
  225. wxcli/commands/mode_management.py +244 -0
  226. wxcli/commands/my_call_settings.py +3577 -0
  227. wxcli/commands/numbers.py +405 -0
  228. wxcli/commands/operating_modes.py +410 -0
  229. wxcli/commands/org_contacts.py +284 -0
  230. wxcli/commands/org_health_cli.py +55 -0
  231. wxcli/commands/org_settings.py +71 -0
  232. wxcli/commands/organizations.py +83 -0
  233. wxcli/commands/paging_group.py +257 -0
  234. wxcli/commands/partner_admins.py +141 -0
  235. wxcli/commands/partner_reports.py +188 -0
  236. wxcli/commands/partner_tags.py +216 -0
  237. wxcli/commands/people.py +279 -0
  238. wxcli/commands/person_call_settings.py +71 -0
  239. wxcli/commands/pstn.py +280 -0
  240. wxcli/commands/recording_report.py +154 -0
  241. wxcli/commands/report_templates.py +38 -0
  242. wxcli/commands/reports.py +144 -0
  243. wxcli/commands/resource_group_memberships.py +160 -0
  244. wxcli/commands/resource_groups.py +67 -0
  245. wxcli/commands/roles.py +63 -0
  246. wxcli/commands/room_tabs.py +160 -0
  247. wxcli/commands/rooms.py +225 -0
  248. wxcli/commands/scim_bulk.py +46 -0
  249. wxcli/commands/scim_groups.py +246 -0
  250. wxcli/commands/scim_schemas.py +82 -0
  251. wxcli/commands/scim_users.py +283 -0
  252. wxcli/commands/security_audit.py +54 -0
  253. wxcli/commands/service_apps.py +51 -0
  254. wxcli/commands/single_number_reach.py +209 -0
  255. wxcli/commands/team_memberships.py +155 -0
  256. wxcli/commands/teams.py +153 -0
  257. wxcli/commands/ucm_profile.py +42 -0
  258. wxcli/commands/update.py +219 -0
  259. wxcli/commands/user_settings.py +5116 -0
  260. wxcli/commands/video_mesh.py +1090 -0
  261. wxcli/commands/virtual_extensions.py +502 -0
  262. wxcli/commands/virtual_line_settings.py +2072 -0
  263. wxcli/commands/webhooks.py +176 -0
  264. wxcli/commands/wholesale_billing_reports.py +147 -0
  265. wxcli/commands/wholesale_provisioning.py +523 -0
  266. wxcli/commands/workspace_locations.py +339 -0
  267. wxcli/commands/workspace_metrics.py +103 -0
  268. wxcli/commands/workspace_personalization.py +70 -0
  269. wxcli/commands/workspace_settings.py +3347 -0
  270. wxcli/commands/workspaces.py +279 -0
  271. wxcli/commands/xapi.py +114 -0
  272. wxcli/config.py +139 -0
  273. wxcli/errors.py +77 -0
  274. wxcli/main.py +210 -0
  275. wxcli/migration/CLAUDE.md +106 -0
  276. wxcli/migration/__init__.py +1 -0
  277. wxcli/migration/advisory/CLAUDE.md +196 -0
  278. wxcli/migration/advisory/__init__.py +46 -0
  279. wxcli/migration/advisory/advisor.py +107 -0
  280. wxcli/migration/advisory/advisory_patterns.py +2552 -0
  281. wxcli/migration/advisory/recommendation_rules.py +835 -0
  282. wxcli/migration/cucm/CLAUDE.md +74 -0
  283. wxcli/migration/cucm/__init__.py +5 -0
  284. wxcli/migration/cucm/connection.py +265 -0
  285. wxcli/migration/cucm/discovery.py +225 -0
  286. wxcli/migration/cucm/extractors/__init__.py +1 -0
  287. wxcli/migration/cucm/extractors/announcements.py +92 -0
  288. wxcli/migration/cucm/extractors/base.py +90 -0
  289. wxcli/migration/cucm/extractors/device_profiles.py +98 -0
  290. wxcli/migration/cucm/extractors/devices.py +193 -0
  291. wxcli/migration/cucm/extractors/e911.py +103 -0
  292. wxcli/migration/cucm/extractors/features.py +309 -0
  293. wxcli/migration/cucm/extractors/helpers.py +73 -0
  294. wxcli/migration/cucm/extractors/informational.py +295 -0
  295. wxcli/migration/cucm/extractors/locations.py +221 -0
  296. wxcli/migration/cucm/extractors/moh.py +100 -0
  297. wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
  298. wxcli/migration/cucm/extractors/routing.py +493 -0
  299. wxcli/migration/cucm/extractors/shared_lines.py +146 -0
  300. wxcli/migration/cucm/extractors/templates.py +229 -0
  301. wxcli/migration/cucm/extractors/tier4.py +173 -0
  302. wxcli/migration/cucm/extractors/users.py +240 -0
  303. wxcli/migration/cucm/extractors/voicemail.py +243 -0
  304. wxcli/migration/cucm/extractors/workspaces.py +88 -0
  305. wxcli/migration/cucm/unity_connection.py +304 -0
  306. wxcli/migration/execute/CLAUDE.md +372 -0
  307. wxcli/migration/execute/__init__.py +303 -0
  308. wxcli/migration/execute/batch.py +277 -0
  309. wxcli/migration/execute/dependency.py +483 -0
  310. wxcli/migration/execute/engine.py +964 -0
  311. wxcli/migration/execute/handlers.py +2232 -0
  312. wxcli/migration/execute/planner.py +1939 -0
  313. wxcli/migration/execute/runtime.py +571 -0
  314. wxcli/migration/export/CLAUDE.md +49 -0
  315. wxcli/migration/export/__init__.py +8 -0
  316. wxcli/migration/export/csv_export.py +126 -0
  317. wxcli/migration/export/deployment_plan.py +479 -0
  318. wxcli/migration/export/json_export.py +60 -0
  319. wxcli/migration/models.py +941 -0
  320. wxcli/migration/phone_models.py +50 -0
  321. wxcli/migration/preflight/CLAUDE.md +52 -0
  322. wxcli/migration/preflight/__init__.py +89 -0
  323. wxcli/migration/preflight/checks.py +911 -0
  324. wxcli/migration/preflight/runner.py +293 -0
  325. wxcli/migration/rate_limiter.py +144 -0
  326. wxcli/migration/report/CLAUDE.md +245 -0
  327. wxcli/migration/report/__init__.py +7 -0
  328. wxcli/migration/report/appendix.py +2437 -0
  329. wxcli/migration/report/assembler.py +183 -0
  330. wxcli/migration/report/charts.py +263 -0
  331. wxcli/migration/report/executive.py +776 -0
  332. wxcli/migration/report/explainer.py +704 -0
  333. wxcli/migration/report/helpers.py +74 -0
  334. wxcli/migration/report/ingest.py +152 -0
  335. wxcli/migration/report/notice_templates.py +192 -0
  336. wxcli/migration/report/score.py +375 -0
  337. wxcli/migration/report/styles.py +1052 -0
  338. wxcli/migration/report/user_diff.py +1052 -0
  339. wxcli/migration/report/user_notice.py +425 -0
  340. wxcli/migration/state.py +139 -0
  341. wxcli/migration/store.py +860 -0
  342. wxcli/migration/transform/CLAUDE.md +107 -0
  343. wxcli/migration/transform/__init__.py +12 -0
  344. wxcli/migration/transform/analysis_pipeline.py +453 -0
  345. wxcli/migration/transform/analyzers/__init__.py +142 -0
  346. wxcli/migration/transform/analyzers/css_permission.py +189 -0
  347. wxcli/migration/transform/analyzers/css_routing.py +335 -0
  348. wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
  349. wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
  350. wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
  351. wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
  352. wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
  353. wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
  354. wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
  355. wxcli/migration/transform/analyzers/missing_data.py +300 -0
  356. wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
  357. wxcli/migration/transform/analyzers/shared_line.py +170 -0
  358. wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
  359. wxcli/migration/transform/analyzers/workspace_license.py +212 -0
  360. wxcli/migration/transform/cross_reference.py +1136 -0
  361. wxcli/migration/transform/cucm_pattern.py +246 -0
  362. wxcli/migration/transform/decisions.py +301 -0
  363. wxcli/migration/transform/e164.py +145 -0
  364. wxcli/migration/transform/engine.py +256 -0
  365. wxcli/migration/transform/mappers/CLAUDE.md +123 -0
  366. wxcli/migration/transform/mappers/__init__.py +76 -0
  367. wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
  368. wxcli/migration/transform/mappers/base.py +190 -0
  369. wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
  370. wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
  371. wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
  372. wxcli/migration/transform/mappers/css_mapper.py +868 -0
  373. wxcli/migration/transform/mappers/dect_mapper.py +367 -0
  374. wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
  375. wxcli/migration/transform/mappers/device_mapper.py +227 -0
  376. wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
  377. wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
  378. wxcli/migration/transform/mappers/e911_mapper.py +129 -0
  379. wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
  380. wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
  381. wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
  382. wxcli/migration/transform/mappers/line_mapper.py +310 -0
  383. wxcli/migration/transform/mappers/location_mapper.py +235 -0
  384. wxcli/migration/transform/mappers/moh_mapper.py +114 -0
  385. wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
  386. wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
  387. wxcli/migration/transform/mappers/routing_mapper.py +821 -0
  388. wxcli/migration/transform/mappers/snr_mapper.py +201 -0
  389. wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
  390. wxcli/migration/transform/mappers/user_mapper.py +264 -0
  391. wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
  392. wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
  393. wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
  394. wxcli/migration/transform/normalizers.py +2008 -0
  395. wxcli/migration/transform/pattern_converter.py +106 -0
  396. wxcli/migration/transform/pipeline.py +271 -0
  397. wxcli/migration/transform/rules.py +255 -0
  398. wxcli/org_health/CLAUDE.md +63 -0
  399. wxcli/org_health/__init__.py +7 -0
  400. wxcli/org_health/analyze.py +93 -0
  401. wxcli/org_health/checks.py +458 -0
  402. wxcli/org_health/collector.py +62 -0
  403. wxcli/org_health/models.py +78 -0
  404. wxcli/org_health/report.py +300 -0
  405. wxcli/output.py +101 -0
  406. wxcli-1.2.0.dist-info/METADATA +505 -0
  407. wxcli-1.2.0.dist-info/RECORD +413 -0
  408. wxcli-1.2.0.dist-info/WHEEL +5 -0
  409. wxcli-1.2.0.dist-info/entry_points.txt +2 -0
  410. wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
  411. wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
  412. wxcli-1.2.0.dist-info/scm_version.json +8 -0
  413. wxcli-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1052 @@
1
+ """CSS design system for the CUCM assessment report v4 (Editorial + v3 Data).
2
+
3
+ Single constant ``REPORT_CSS`` — embedded directly into the HTML report
4
+ by the assembler. Google Fonts loaded via <link> tags in the <head>
5
+ (see GOOGLE_FONTS_LINKS).
6
+ """
7
+
8
+ GOOGLE_FONTS_LINKS = (
9
+ '<link rel="preconnect" href="https://fonts.googleapis.com">'
10
+ '<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>'
11
+ '<link href="https://fonts.googleapis.com/css2?'
12
+ 'family=IBM+Plex+Mono:wght@400;500&'
13
+ 'family=Lora:ital,wght@0,400;0,600;0,700;1,400&'
14
+ 'family=Source+Sans+3:wght@300;400;500;600;700&display=swap" rel="stylesheet">'
15
+ )
16
+
17
+ REPORT_CSS = """\
18
+ /* ==========================================================================
19
+ CUCM Assessment Report v4 — Editorial Design System
20
+ ========================================================================== */
21
+
22
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
23
+
24
+ :root {
25
+ /* -- Warm neutrals ---------------------------------------------------- */
26
+ --warm-50: #fdf8f3;
27
+ --warm-100: #f9efe4;
28
+ --warm-200: #f0dcc6;
29
+ --warm-300: #e3c4a0;
30
+ --warm-400: #d4a574;
31
+ --warm-500: #b8864e;
32
+ --warm-600: #96693a;
33
+ --warm-700: #6b4a2a;
34
+ --warm-800: #45301c;
35
+ --warm-900: #2a1c10;
36
+
37
+ --slate-50: #f8f9fa;
38
+ --slate-100: #eef0f3;
39
+ --slate-200: #dde1e7;
40
+ --slate-300: #bcc3cd;
41
+ --slate-400: #8e97a5;
42
+ --slate-500: #636e7e;
43
+ --slate-600: #4a5363;
44
+ --slate-700: #353d4a;
45
+ --slate-800: #242a33;
46
+ --slate-900: #181c22;
47
+
48
+ /* -- Brand / status palette ------------------------------------------- */
49
+ --primary: #00897B;
50
+ --primary-light: #E0F2F1;
51
+ --success: #2E7D32;
52
+ --success-light: #E8F5E9;
53
+ --warning: #EF6C00;
54
+ --warning-light: #FFF3E0;
55
+ --critical: #C62828;
56
+ --critical-light:#FFEBEE;
57
+
58
+ /* Legacy aliases (charts.py, appendix.py, explainer.py reference these) */
59
+ --color-primary: #00897B;
60
+ --color-success: #2E7D32;
61
+ --color-warning: #EF6C00;
62
+ --color-critical: #C62828;
63
+ --color-neutral: var(--slate-700);
64
+ --color-bg: var(--warm-50);
65
+ --color-border: var(--warm-200);
66
+ --color-text: var(--slate-800);
67
+ --color-text-muted: var(--slate-500);
68
+ --color-text-light: var(--slate-400);
69
+ --color-zebra: var(--warm-100);
70
+
71
+ /* -- Typography ------------------------------------------------------- */
72
+ --font-display: 'Lora', Georgia, serif;
73
+ --font-body: 'Source Sans 3', 'Source Sans Pro', system-ui, sans-serif;
74
+ --font-mono: 'IBM Plex Mono', 'Menlo', monospace;
75
+ --font-family: var(--font-body);
76
+
77
+ /* -- Spacing (8px grid) ----------------------------------------------- */
78
+ --spacing-xs: 4px;
79
+ --spacing-sm: 8px;
80
+ --spacing-md: 16px;
81
+ --spacing-lg: 24px;
82
+ --spacing-xl: 32px;
83
+ --spacing-xxl: 48px;
84
+
85
+ /* -- Radii ------------------------------------------------------------ */
86
+ --radius-sm: 4px;
87
+ --radius-md: 8px;
88
+ --radius-lg: 12px;
89
+ }
90
+
91
+
92
+ /* ==========================================================================
93
+ Base
94
+ ========================================================================== */
95
+
96
+ html {
97
+ font-size: 17px;
98
+ -webkit-font-smoothing: antialiased;
99
+ -moz-osx-font-smoothing: grayscale;
100
+ }
101
+
102
+ body {
103
+ font-family: var(--font-body);
104
+ background: var(--warm-50);
105
+ color: var(--slate-800);
106
+ line-height: 1.6;
107
+ }
108
+
109
+ a { color: var(--primary); text-decoration: none; }
110
+ a:hover { text-decoration: underline; }
111
+
112
+
113
+ /* ==========================================================================
114
+ Page Header
115
+ ========================================================================== */
116
+
117
+ .page-header {
118
+ background: var(--slate-900);
119
+ color: var(--warm-100);
120
+ padding: 2rem 2.5rem 1.75rem;
121
+ }
122
+
123
+ .page-header h1 {
124
+ font-family: var(--font-display);
125
+ font-size: 1.75rem;
126
+ font-weight: 700;
127
+ letter-spacing: -0.01em;
128
+ margin-bottom: 0.25rem;
129
+ color: white;
130
+ border: none;
131
+ }
132
+
133
+ .page-header .subtitle {
134
+ font-size: 0.95rem;
135
+ color: var(--slate-400);
136
+ font-weight: 300;
137
+ }
138
+
139
+ .page-header .brand {
140
+ font-family: var(--font-display);
141
+ font-size: 1.15rem;
142
+ font-weight: 600;
143
+ color: var(--warm-200);
144
+ margin-bottom: 0.125rem;
145
+ }
146
+
147
+ .page-header .meta {
148
+ font-size: 0.8rem;
149
+ color: var(--slate-400);
150
+ }
151
+
152
+
153
+ /* ==========================================================================
154
+ Sidebar + Content Layout
155
+ ========================================================================== */
156
+
157
+ .main-layout {
158
+ display: grid;
159
+ grid-template-columns: 320px 1fr;
160
+ min-height: calc(100vh - 200px);
161
+ }
162
+
163
+ .step-list {
164
+ border-right: 1px solid var(--slate-200);
165
+ background: white;
166
+ overflow-y: auto;
167
+ max-height: calc(100vh - 200px);
168
+ position: sticky;
169
+ top: 0;
170
+ }
171
+
172
+ .step-list-section { padding: 0.625rem 0 0; }
173
+
174
+ .step-list-section-title {
175
+ font-family: var(--font-display);
176
+ font-size: 0.7rem;
177
+ font-weight: 700;
178
+ text-transform: uppercase;
179
+ letter-spacing: 0.1em;
180
+ color: var(--slate-400);
181
+ padding: 0.5rem 1.25rem 0.375rem;
182
+ }
183
+
184
+ .step-item {
185
+ display: flex;
186
+ align-items: center;
187
+ gap: 0.75rem;
188
+ padding: 0.625rem 1.25rem;
189
+ cursor: pointer;
190
+ border-left: 3px solid transparent;
191
+ transition: all 0.15s ease;
192
+ text-decoration: none;
193
+ color: var(--slate-700);
194
+ font-size: 0.85rem;
195
+ font-weight: 500;
196
+ }
197
+
198
+ .step-item:hover { background: var(--warm-100); text-decoration: none; }
199
+ .step-item.active { background: var(--warm-100); border-left-color: var(--primary); color: var(--primary); }
200
+
201
+ .step-icon {
202
+ font-family: var(--font-mono);
203
+ font-size: 0.65rem;
204
+ font-weight: 500;
205
+ color: white;
206
+ width: 22px;
207
+ height: 22px;
208
+ border-radius: 50%;
209
+ display: flex;
210
+ align-items: center;
211
+ justify-content: center;
212
+ flex-shrink: 0;
213
+ background: var(--primary);
214
+ }
215
+
216
+ .step-icon.exec { background: var(--primary); }
217
+ .step-icon.tech { background: var(--slate-500); }
218
+
219
+ .detail-panel {
220
+ padding: 2.5rem 3rem;
221
+ overflow-y: auto;
222
+ max-height: calc(100vh - 200px);
223
+ }
224
+
225
+
226
+ /* ==========================================================================
227
+ Headings
228
+ ========================================================================== */
229
+
230
+ h1, h2, h3, h4 {
231
+ font-family: var(--font-display);
232
+ font-weight: 600;
233
+ color: var(--slate-800);
234
+ line-height: 1.25;
235
+ }
236
+
237
+ h2 {
238
+ font-size: 1.5rem;
239
+ font-weight: 700;
240
+ color: var(--slate-900);
241
+ margin: 0 0 1.25rem 0;
242
+ padding-bottom: 0.75rem;
243
+ border-bottom: 2px solid var(--warm-200);
244
+ }
245
+
246
+ h3 {
247
+ font-size: 1.1rem;
248
+ font-weight: 600;
249
+ color: var(--slate-800);
250
+ margin: 1.75rem 0 0.75rem 0;
251
+ }
252
+
253
+ h4 {
254
+ font-size: 0.95rem;
255
+ font-weight: 600;
256
+ margin: 1.25rem 0 0.5rem 0;
257
+ }
258
+
259
+
260
+ /* ==========================================================================
261
+ Prose
262
+ ========================================================================== */
263
+
264
+ p { margin: 0 0 1rem; }
265
+
266
+ .muted { color: var(--slate-500); }
267
+ .small { font-size: 0.85rem; }
268
+
269
+ .lead-sentence {
270
+ font-family: var(--font-display);
271
+ font-size: 1.05rem;
272
+ font-weight: 400;
273
+ font-style: italic;
274
+ color: var(--slate-700);
275
+ line-height: 1.5;
276
+ margin-bottom: 1.5rem;
277
+ }
278
+
279
+
280
+ /* ==========================================================================
281
+ Sections
282
+ ========================================================================== */
283
+
284
+ section { margin-bottom: 2.5rem; }
285
+
286
+
287
+ /* ==========================================================================
288
+ Environment Donut (floated beside People + Devices)
289
+ ========================================================================== */
290
+
291
+ .env-donut {
292
+ float: right;
293
+ width: 420px;
294
+ margin: 0.5rem 8rem 1rem 2rem;
295
+ }
296
+
297
+ .env-donut svg {
298
+ width: 100%;
299
+ height: auto;
300
+ }
301
+
302
+
303
+ /* ==========================================================================
304
+ Stat Grid & Stat Cards
305
+ ========================================================================== */
306
+
307
+ .stat-grid {
308
+ display: grid;
309
+ grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
310
+ gap: 0.75rem;
311
+ margin: 0.75rem 0 1.5rem;
312
+ }
313
+
314
+ .stat-card {
315
+ background: var(--warm-100);
316
+ border-radius: var(--radius-md);
317
+ padding: 0.875rem 1rem;
318
+ }
319
+
320
+ .stat-card .stat-label {
321
+ font-size: 0.65rem;
322
+ font-weight: 600;
323
+ text-transform: uppercase;
324
+ letter-spacing: 0.06em;
325
+ color: var(--slate-500);
326
+ margin-bottom: 0.25rem;
327
+ }
328
+
329
+ .stat-card .stat-value,
330
+ .stat-card .stat-number {
331
+ font-family: var(--font-mono);
332
+ font-size: 1.25rem;
333
+ font-weight: 500;
334
+ color: var(--slate-800);
335
+ }
336
+
337
+ /* Colored variants */
338
+ .stat-card.success { border-left: 3px solid var(--success); }
339
+ .stat-card.warning { border-left: 3px solid var(--warning); }
340
+ .stat-card.critical { border-left: 3px solid var(--critical); }
341
+
342
+ .stat-card.success .stat-value { color: var(--success); }
343
+ .stat-card.warning .stat-value { color: var(--warning); }
344
+ .stat-card.critical .stat-value { color: var(--critical); }
345
+
346
+
347
+ /* ==========================================================================
348
+ Tables — deg-table style
349
+ ========================================================================== */
350
+
351
+ table {
352
+ width: 100%;
353
+ border-collapse: collapse;
354
+ font-size: 0.85rem;
355
+ margin: 0.75rem 0 1.5rem;
356
+ font-variant-numeric: tabular-nums;
357
+ }
358
+
359
+ thead th {
360
+ text-align: left;
361
+ font-weight: 600;
362
+ color: var(--slate-600);
363
+ padding: 0.5rem 0.75rem;
364
+ border-bottom: 2px solid var(--slate-200);
365
+ font-size: 0.7rem;
366
+ text-transform: uppercase;
367
+ letter-spacing: 0.04em;
368
+ background: transparent;
369
+ white-space: nowrap;
370
+ }
371
+
372
+ tbody td {
373
+ padding: 0.5rem 0.75rem;
374
+ border-bottom: 1px solid var(--warm-200);
375
+ color: var(--slate-700);
376
+ vertical-align: top;
377
+ }
378
+
379
+ tbody tr:last-child td { border-bottom: none; }
380
+
381
+ tbody tr:hover { background: var(--warm-100); }
382
+
383
+ /* Right-align numeric columns */
384
+ td.num, th.num {
385
+ text-align: right;
386
+ font-family: var(--font-mono);
387
+ font-variant-numeric: tabular-nums;
388
+ }
389
+
390
+
391
+ /* ==========================================================================
392
+ Badges
393
+ ========================================================================== */
394
+
395
+ .badge {
396
+ display: inline-block;
397
+ font-size: 0.65rem;
398
+ font-weight: 600;
399
+ padding: 0.15rem 0.5rem;
400
+ border-radius: 3px;
401
+ text-transform: uppercase;
402
+ letter-spacing: 0.03em;
403
+ }
404
+
405
+ .badge-direct,
406
+ .badge-low { background: var(--success-light); color: var(--success); }
407
+ .badge-approx,
408
+ .badge-medium { background: var(--warning-light); color: var(--warning); }
409
+ .badge-decision,
410
+ .badge-critical,
411
+ .badge-high { background: var(--critical-light); color: var(--critical); }
412
+ .badge-auto { background: var(--primary-light); color: var(--primary); }
413
+
414
+
415
+ /* ==========================================================================
416
+ Callout Boxes
417
+ ========================================================================== */
418
+
419
+ .callout {
420
+ border-left: 3px solid var(--warning);
421
+ background: var(--warning-light);
422
+ padding: 0.875rem 1.125rem;
423
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
424
+ font-size: 0.875rem;
425
+ color: var(--warm-700);
426
+ margin: 0.75rem 0;
427
+ }
428
+
429
+ .callout.success { border-left-color: var(--success); background: var(--success-light); }
430
+ .callout.critical { border-left-color: var(--critical); background: var(--critical-light); color: var(--critical); }
431
+ .callout.info { border-left-color: var(--primary); background: var(--primary-light); color: var(--slate-700); }
432
+
433
+ .callout strong { font-weight: 600; }
434
+ .callout p { margin: 0 0 0.5rem; }
435
+ .callout p:last-child { margin-bottom: 0; }
436
+
437
+
438
+ /* ==========================================================================
439
+ Explanations (decision cards)
440
+ ========================================================================== */
441
+
442
+ .explanation {
443
+ padding: 1rem 1.25rem;
444
+ margin: 0.75rem 0;
445
+ border-left: 3px solid var(--primary);
446
+ background: var(--primary-light);
447
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
448
+ }
449
+
450
+ .explanation h4 {
451
+ margin: 0 0 0.375rem 0;
452
+ font-size: 0.9rem;
453
+ color: var(--slate-800);
454
+ }
455
+
456
+ .explanation p {
457
+ font-size: 0.85rem;
458
+ color: var(--slate-700);
459
+ margin: 0 0 0.375rem;
460
+ line-height: 1.55;
461
+ }
462
+
463
+ .explanation .reassurance {
464
+ color: var(--slate-500);
465
+ font-style: italic;
466
+ margin-bottom: 0;
467
+ }
468
+
469
+ /* Color-code explanations by severity */
470
+ .explanation.severity-critical { border-left-color: var(--critical); background: var(--critical-light); }
471
+ .explanation.severity-high { border-left-color: var(--warning); background: var(--warning-light); }
472
+ .explanation.severity-medium { border-left-color: var(--warning); background: var(--warning-light); }
473
+ .explanation.severity-low { border-left-color: var(--success); background: var(--success-light); }
474
+
475
+
476
+ /* ==========================================================================
477
+ Score Layout (v3 data, v1 theme)
478
+ ========================================================================== */
479
+
480
+ .score-layout {
481
+ display: grid;
482
+ grid-template-columns: 200px 1fr;
483
+ gap: 2rem;
484
+ align-items: start;
485
+ margin: 1rem 0 2rem;
486
+ }
487
+
488
+ .score-gauge {
489
+ display: flex;
490
+ justify-content: center;
491
+ align-items: center;
492
+ }
493
+
494
+ .score-gauge svg {
495
+ width: 100%;
496
+ height: auto;
497
+ max-width: 180px;
498
+ }
499
+
500
+
501
+ /* -- Score breakdown bars ------------------------------------------------- */
502
+ .score-breakdown {
503
+ display: flex;
504
+ flex-direction: column;
505
+ gap: 8px;
506
+ }
507
+
508
+ .score-breakdown .factor-scale {
509
+ display: grid;
510
+ grid-template-columns: 140px 1fr;
511
+ gap: 0.5rem;
512
+ font-size: 0.65rem;
513
+ font-weight: 600;
514
+ text-transform: uppercase;
515
+ letter-spacing: 0.06em;
516
+ color: var(--slate-400);
517
+ margin-bottom: 2px;
518
+ }
519
+
520
+ .score-breakdown .factor-scale-title {
521
+ text-align: right;
522
+ }
523
+
524
+ .score-breakdown .factor-scale-low,
525
+ .score-breakdown .factor-scale-high {
526
+ display: inline;
527
+ }
528
+
529
+ .score-breakdown .factor-scale .factor-scale-low {
530
+ float: left;
531
+ }
532
+
533
+ .score-breakdown .factor-scale .factor-scale-high {
534
+ float: right;
535
+ }
536
+
537
+ .score-breakdown .factor-row {
538
+ display: grid;
539
+ grid-template-columns: 140px 1fr;
540
+ align-items: center;
541
+ gap: 0.5rem;
542
+ font-size: 0.85rem;
543
+ }
544
+
545
+ .score-breakdown .factor-label {
546
+ color: var(--slate-500);
547
+ text-align: right;
548
+ white-space: nowrap;
549
+ }
550
+
551
+ .score-breakdown .factor-bar {
552
+ height: 10px;
553
+ border-radius: 5px;
554
+ background: var(--slate-100);
555
+ overflow: hidden;
556
+ }
557
+
558
+ .score-breakdown .factor-fill {
559
+ height: 100%;
560
+ border-radius: 5px;
561
+ }
562
+
563
+
564
+ /* -- Key findings --------------------------------------------------------- */
565
+ .key-findings {
566
+ list-style: none;
567
+ padding: 0;
568
+ margin: 1rem 0;
569
+ }
570
+
571
+ .key-findings li {
572
+ display: flex;
573
+ gap: 10px;
574
+ align-items: flex-start;
575
+ padding: 0.5rem 0;
576
+ border-bottom: 1px solid var(--warm-200);
577
+ font-size: 0.875rem;
578
+ color: var(--slate-700);
579
+ line-height: 1.5;
580
+ }
581
+
582
+ .key-findings li:last-child {
583
+ border-bottom: none;
584
+ }
585
+
586
+ .key-findings .finding-icon {
587
+ flex-shrink: 0;
588
+ width: 22px;
589
+ height: 22px;
590
+ border-radius: 50%;
591
+ display: flex;
592
+ align-items: center;
593
+ justify-content: center;
594
+ font-weight: 700;
595
+ font-size: 0.7rem;
596
+ margin-top: 2px;
597
+ }
598
+
599
+ .key-findings .finding-icon.check {
600
+ background: var(--success-light);
601
+ color: var(--success);
602
+ }
603
+
604
+ .key-findings .finding-icon.alert {
605
+ background: var(--warning-light);
606
+ color: var(--warning);
607
+ }
608
+
609
+
610
+ /* ==========================================================================
611
+ Effort Bands (v3 data, v1 theme)
612
+ ========================================================================== */
613
+
614
+ .effort-band {
615
+ border-left: 3px solid var(--slate-300);
616
+ background: var(--slate-50);
617
+ padding: 0.875rem 1.125rem;
618
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
619
+ margin: 0.75rem 0;
620
+ }
621
+
622
+ .effort-band h4 {
623
+ margin: 0 0 0.375rem 0;
624
+ font-family: var(--font-display);
625
+ font-size: 0.95rem;
626
+ }
627
+
628
+ .effort-band p {
629
+ font-size: 0.85rem;
630
+ color: var(--slate-500);
631
+ margin-bottom: 0.5rem;
632
+ }
633
+
634
+ .effort-band.auto {
635
+ border-left-color: var(--success);
636
+ background: var(--success-light);
637
+ }
638
+ .effort-band.auto h4 { color: var(--success); }
639
+
640
+ .effort-band.planning {
641
+ border-left-color: var(--warning);
642
+ background: var(--warning-light);
643
+ }
644
+ .effort-band.planning h4 { color: var(--warning); }
645
+
646
+ .effort-band.manual {
647
+ border-left-color: var(--critical);
648
+ background: var(--critical-light);
649
+ }
650
+ .effort-band.manual h4 { color: var(--critical); }
651
+
652
+ .effort-band ul {
653
+ margin: 0;
654
+ padding-left: var(--spacing-lg);
655
+ font-size: 0.85rem;
656
+ color: var(--slate-700);
657
+ }
658
+
659
+ .effort-band ul li {
660
+ margin-bottom: 4px;
661
+ }
662
+
663
+
664
+ /* -- Verdict callout ------------------------------------------------------ */
665
+ .verdict {
666
+ padding: 1rem 1.25rem;
667
+ border-left: 3px solid var(--primary);
668
+ background: var(--primary-light);
669
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
670
+ margin: 0.75rem 0 1.5rem;
671
+ font-size: 0.9rem;
672
+ line-height: 1.6;
673
+ color: var(--slate-700);
674
+ }
675
+
676
+
677
+ /* -- CTA box -------------------------------------------------------------- */
678
+ .cta-box {
679
+ background: var(--primary-light);
680
+ border: 2px solid var(--primary);
681
+ border-radius: var(--radius-md);
682
+ padding: var(--spacing-lg);
683
+ text-align: center;
684
+ margin: var(--spacing-lg) 0;
685
+ }
686
+
687
+ .cta-box h3 {
688
+ color: var(--primary);
689
+ margin-top: 0;
690
+ }
691
+
692
+
693
+ /* -- Decision resolution bar ---------------------------------------------- */
694
+ .resolution-bar {
695
+ display: flex;
696
+ height: 20px;
697
+ border-radius: var(--radius-sm);
698
+ overflow: hidden;
699
+ margin: var(--spacing-sm) 0;
700
+ }
701
+
702
+ .resolution-bar .bar-auto { background: var(--success); }
703
+ .resolution-bar .bar-planning { background: var(--warning); }
704
+ .resolution-bar .bar-manual { background: var(--critical); }
705
+
706
+
707
+ /* ==========================================================================
708
+ Chart Containers
709
+ ========================================================================== */
710
+
711
+ .chart-container {
712
+ display: flex;
713
+ flex-wrap: wrap;
714
+ gap: 1.5rem;
715
+ justify-content: center;
716
+ margin: 1.5rem 0;
717
+ }
718
+
719
+ .chart-container > div {
720
+ flex: 1 1 300px;
721
+ min-width: 250px;
722
+ max-width: 500px;
723
+ }
724
+
725
+ .chart-container svg {
726
+ width: 100%;
727
+ height: auto;
728
+ }
729
+
730
+ /* Traffic-light / summary boxes (legacy, kept for chart tests) */
731
+ .summary-boxes {
732
+ display: flex;
733
+ justify-content: center;
734
+ margin: 1rem 0;
735
+ }
736
+
737
+ .summary-boxes svg {
738
+ width: 100%;
739
+ max-width: 450px;
740
+ height: auto;
741
+ }
742
+
743
+
744
+ /* ==========================================================================
745
+ Details / Summary (collapsible appendix sections)
746
+ ========================================================================== */
747
+
748
+ details {
749
+ margin: 1rem 0;
750
+ border: 1px solid var(--warm-200);
751
+ border-radius: var(--radius-md);
752
+ overflow: hidden;
753
+ }
754
+
755
+ details[open] {
756
+ border-color: var(--primary);
757
+ }
758
+
759
+ summary {
760
+ padding: 0.75rem 1rem;
761
+ background: white;
762
+ font-family: var(--font-display);
763
+ font-weight: 600;
764
+ font-size: 0.95rem;
765
+ color: var(--slate-800);
766
+ cursor: pointer;
767
+ list-style: none;
768
+ user-select: none;
769
+ display: flex;
770
+ align-items: center;
771
+ gap: 0.75rem;
772
+ }
773
+
774
+ summary::-webkit-details-marker { display: none; }
775
+
776
+ summary::before {
777
+ content: '\\25B6';
778
+ display: inline-block;
779
+ font-size: 0.65rem;
780
+ color: var(--slate-400);
781
+ transition: transform 0.15s ease;
782
+ }
783
+
784
+ details[open] > summary::before {
785
+ transform: rotate(90deg);
786
+ }
787
+
788
+ details[open] > summary {
789
+ border-bottom: 1px solid var(--warm-200);
790
+ color: var(--primary);
791
+ }
792
+
793
+ summary .summary-count {
794
+ font-weight: 400;
795
+ color: var(--slate-500);
796
+ font-size: 0.75rem;
797
+ margin-left: 4px;
798
+ }
799
+
800
+ .details-content {
801
+ padding: var(--spacing-md);
802
+ }
803
+
804
+
805
+ /* ==========================================================================
806
+ Section Indicator (appendix letter labels)
807
+ ========================================================================== */
808
+
809
+ .section-indicator {
810
+ display: inline-flex;
811
+ align-items: center;
812
+ justify-content: center;
813
+ width: 24px;
814
+ height: 24px;
815
+ border-radius: 50%;
816
+ background: var(--primary);
817
+ color: white;
818
+ font-family: var(--font-mono);
819
+ font-size: 0.7rem;
820
+ font-weight: 500;
821
+ flex-shrink: 0;
822
+ }
823
+
824
+
825
+ /* ==========================================================================
826
+ CSS/Partition Topology
827
+ ========================================================================== */
828
+
829
+ .css-topology {
830
+ list-style: none;
831
+ padding: 0;
832
+ margin: var(--spacing-sm) 0;
833
+ font-size: 0.8rem;
834
+ }
835
+
836
+ .css-topology li {
837
+ padding: 4px 0 4px 18px;
838
+ position: relative;
839
+ color: var(--slate-700);
840
+ }
841
+
842
+ .css-topology li::before {
843
+ content: '';
844
+ position: absolute;
845
+ left: 4px;
846
+ top: 10px;
847
+ width: 8px;
848
+ height: 8px;
849
+ border-radius: 50%;
850
+ background: var(--primary);
851
+ }
852
+
853
+ .css-topology .partition {
854
+ padding-left: 36px;
855
+ color: var(--slate-500);
856
+ }
857
+
858
+ .css-topology .partition::before {
859
+ left: 22px;
860
+ width: 6px;
861
+ height: 6px;
862
+ background: var(--slate-300);
863
+ }
864
+
865
+
866
+ /* ==========================================================================
867
+ Report Header (legacy) / Footer
868
+ ========================================================================== */
869
+
870
+ .report-header {
871
+ text-align: center;
872
+ margin-bottom: var(--spacing-xxl);
873
+ }
874
+
875
+ .report-footer {
876
+ background: var(--slate-900);
877
+ color: var(--slate-400);
878
+ text-align: center;
879
+ padding: 1.25rem 2rem;
880
+ font-size: 0.75rem;
881
+ }
882
+
883
+ .report-footer p { margin: 0; }
884
+
885
+
886
+ /* ==========================================================================
887
+ Print Header (hidden on screen)
888
+ ========================================================================== */
889
+
890
+ .print-header {
891
+ display: none;
892
+ }
893
+
894
+
895
+ /* ==========================================================================
896
+ Checklist
897
+ ========================================================================== */
898
+
899
+ .checklist {
900
+ list-style: none;
901
+ padding: 0;
902
+ }
903
+
904
+ .checklist li {
905
+ position: relative;
906
+ padding: 0.5rem 0 0.5rem 2rem;
907
+ font-size: 0.875rem;
908
+ color: var(--slate-700);
909
+ border-bottom: 1px solid var(--warm-200);
910
+ }
911
+
912
+ .checklist li:last-child { border-bottom: none; }
913
+
914
+ .checklist li::before {
915
+ content: '';
916
+ position: absolute;
917
+ left: 0;
918
+ top: 0.75rem;
919
+ width: 16px;
920
+ height: 16px;
921
+ border: 2px solid var(--slate-300);
922
+ border-radius: 3px;
923
+ }
924
+
925
+
926
+ /* ==========================================================================
927
+ Responsive
928
+ ========================================================================== */
929
+
930
+ @media (max-width: 860px) {
931
+ .main-layout { grid-template-columns: 1fr; }
932
+ .step-list {
933
+ max-height: none;
934
+ position: static;
935
+ border-right: none;
936
+ border-bottom: 1px solid var(--slate-200);
937
+ }
938
+ .detail-panel { max-height: none; padding: 1.5rem; }
939
+ }
940
+
941
+
942
+ /* ==========================================================================
943
+ Print Styles
944
+ ========================================================================== */
945
+
946
+ @page {
947
+ size: letter;
948
+ margin: 0.75in;
949
+ }
950
+
951
+ @media print {
952
+ html { font-size: 9.5pt; }
953
+
954
+ body {
955
+ padding: 0;
956
+ color: #000;
957
+ background: #fff;
958
+ }
959
+
960
+ /* Hide sidebar, show linear content */
961
+ .main-layout { display: block; }
962
+ .step-list { display: none; }
963
+ .detail-panel {
964
+ max-height: none;
965
+ padding: 0;
966
+ overflow: visible;
967
+ }
968
+
969
+ /* Hide screen-only elements */
970
+ .page-header { display: none; }
971
+ .no-print { display: none !important; }
972
+
973
+ /* Print header: customer name + date as page header */
974
+ .print-header {
975
+ display: block !important;
976
+ text-align: center;
977
+ margin-bottom: 2rem;
978
+ padding-bottom: 0.75rem;
979
+ border-bottom: 2px solid var(--primary);
980
+ }
981
+
982
+ .print-header h1 {
983
+ font-family: var(--font-display);
984
+ font-size: 20pt;
985
+ color: var(--primary);
986
+ margin-bottom: 0.25rem;
987
+ border: none;
988
+ }
989
+
990
+ .print-header .meta {
991
+ font-size: 9pt;
992
+ color: var(--slate-500);
993
+ }
994
+
995
+ /* Page breaks */
996
+ section {
997
+ page-break-before: always;
998
+ }
999
+
1000
+ section:first-of-type {
1001
+ page-break-before: avoid;
1002
+ }
1003
+
1004
+ h2, h3 {
1005
+ page-break-after: avoid;
1006
+ }
1007
+
1008
+ table, figure, .chart-container, .stat-grid {
1009
+ page-break-inside: avoid;
1010
+ }
1011
+
1012
+ /* Tables: preserve header styling */
1013
+ thead th {
1014
+ border-bottom-color: var(--slate-800) !important;
1015
+ -webkit-print-color-adjust: exact;
1016
+ print-color-adjust: exact;
1017
+ }
1018
+
1019
+ tbody tr:hover { background: inherit; }
1020
+
1021
+ /* Details: force open */
1022
+ details { border: none; }
1023
+ details > summary { display: none; }
1024
+ details > .details-content,
1025
+ details > :not(summary) {
1026
+ display: block !important;
1027
+ padding: 0.5rem 0;
1028
+ }
1029
+
1030
+ /* Badges: preserve colors */
1031
+ .badge, .stat-card, .effort-band, .callout {
1032
+ -webkit-print-color-adjust: exact;
1033
+ print-color-adjust: exact;
1034
+ }
1035
+
1036
+ /* Score gauge: size for print */
1037
+ .score-gauge { max-width: 220px; }
1038
+
1039
+ /* Footer */
1040
+ .report-footer {
1041
+ position: fixed;
1042
+ bottom: 0;
1043
+ left: 0;
1044
+ right: 0;
1045
+ background: transparent;
1046
+ color: var(--slate-500);
1047
+ font-size: 8pt;
1048
+ border-top: 1px solid var(--slate-200);
1049
+ padding: 4px 0;
1050
+ }
1051
+ }
1052
+ """