coursecode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +322 -0
  3. package/THIRD_PARTY_NOTICES.md +22 -0
  4. package/bin/cli.js +331 -0
  5. package/framework/assets/logo-coursecode-black.svg +14 -0
  6. package/framework/assets/logo-coursecode-white.svg +14 -0
  7. package/framework/assets/logo-coursecode.svg +14 -0
  8. package/framework/css/01-base.css +160 -0
  9. package/framework/css/02-layout.css +499 -0
  10. package/framework/css/accessibility.css +834 -0
  11. package/framework/css/components/accordions.css +710 -0
  12. package/framework/css/components/assessments.css +520 -0
  13. package/framework/css/components/audio-player.css +570 -0
  14. package/framework/css/components/badges.css +80 -0
  15. package/framework/css/components/breadcrumbs.css +87 -0
  16. package/framework/css/components/buttons.css +707 -0
  17. package/framework/css/components/callouts.css +1280 -0
  18. package/framework/css/components/cards.css +475 -0
  19. package/framework/css/components/carousel.css +193 -0
  20. package/framework/css/components/checkbox-group.css +123 -0
  21. package/framework/css/components/checklist.css +203 -0
  22. package/framework/css/components/collapse.css +96 -0
  23. package/framework/css/components/comparison.css +33 -0
  24. package/framework/css/components/content-image.css +36 -0
  25. package/framework/css/components/document-gallery.css +425 -0
  26. package/framework/css/components/dropdown.css +115 -0
  27. package/framework/css/components/embed-frame.css +142 -0
  28. package/framework/css/components/engagement.css +412 -0
  29. package/framework/css/components/features.css +35 -0
  30. package/framework/css/components/flip-cards.css +253 -0
  31. package/framework/css/components/footer.css +353 -0
  32. package/framework/css/components/forms.css +294 -0
  33. package/framework/css/components/hero.css +216 -0
  34. package/framework/css/components/images.css +528 -0
  35. package/framework/css/components/interactive-timeline.css +274 -0
  36. package/framework/css/components/intro-cards.css +30 -0
  37. package/framework/css/components/lightbox.css +666 -0
  38. package/framework/css/components/loading.css +65 -0
  39. package/framework/css/components/modals.css +235 -0
  40. package/framework/css/components/notifications.css +107 -0
  41. package/framework/css/components/quote.css +150 -0
  42. package/framework/css/components/sidebar.css +684 -0
  43. package/framework/css/components/slide-header.css +52 -0
  44. package/framework/css/components/spinner.css +62 -0
  45. package/framework/css/components/stats.css +44 -0
  46. package/framework/css/components/steps.css +232 -0
  47. package/framework/css/components/tables.css +90 -0
  48. package/framework/css/components/tabs.css +347 -0
  49. package/framework/css/components/timeline.css +154 -0
  50. package/framework/css/components/toggle.css +95 -0
  51. package/framework/css/components/tooltip.css +226 -0
  52. package/framework/css/components/video-player.css +438 -0
  53. package/framework/css/design-tokens.css +707 -0
  54. package/framework/css/framework.css +86 -0
  55. package/framework/css/interactions/accessibility.css +75 -0
  56. package/framework/css/interactions/base.css +92 -0
  57. package/framework/css/interactions/drag-drop.css +295 -0
  58. package/framework/css/interactions/fill-in-the-blank.css +236 -0
  59. package/framework/css/interactions/hotspots.css +69 -0
  60. package/framework/css/interactions/index.css +45 -0
  61. package/framework/css/interactions/interactive-image.css +359 -0
  62. package/framework/css/interactions/likert.css +126 -0
  63. package/framework/css/interactions/matching.css +354 -0
  64. package/framework/css/interactions/numeric-input.css +78 -0
  65. package/framework/css/interactions/sequencing.css +378 -0
  66. package/framework/css/interactions/true-false.css +177 -0
  67. package/framework/css/layouts/article.css +258 -0
  68. package/framework/css/layouts/base.css +30 -0
  69. package/framework/css/layouts/canvas.css +38 -0
  70. package/framework/css/layouts/focused.css +236 -0
  71. package/framework/css/layouts/index.css +29 -0
  72. package/framework/css/layouts/presentation.css +191 -0
  73. package/framework/css/layouts/traditional.css +52 -0
  74. package/framework/css/responsive.css +439 -0
  75. package/framework/css/utilities/accessibility-utils.css +59 -0
  76. package/framework/css/utilities/animations.css +419 -0
  77. package/framework/css/utilities/borders.css +72 -0
  78. package/framework/css/utilities/colors.css +76 -0
  79. package/framework/css/utilities/container.css +46 -0
  80. package/framework/css/utilities/decorative.css +442 -0
  81. package/framework/css/utilities/display.css +257 -0
  82. package/framework/css/utilities/flexbox.css +80 -0
  83. package/framework/css/utilities/grid.css +69 -0
  84. package/framework/css/utilities/icons.css +534 -0
  85. package/framework/css/utilities/lists.css +190 -0
  86. package/framework/css/utilities/spacing.css +167 -0
  87. package/framework/css/utilities/tables.css +81 -0
  88. package/framework/css/utilities/typography.css +159 -0
  89. package/framework/css/utilities/visibility.css +117 -0
  90. package/framework/docs/COURSE_AUTHORING_GUIDE.md +1773 -0
  91. package/framework/docs/COURSE_OUTLINE_GUIDE.md +725 -0
  92. package/framework/docs/COURSE_OUTLINE_TEMPLATE.md +161 -0
  93. package/framework/docs/DATA_MODEL.md +409 -0
  94. package/framework/docs/FRAMEWORK_GUIDE.md +1088 -0
  95. package/framework/docs/USER_GUIDE.md +583 -0
  96. package/framework/docs/examples/cloudflare-channel-relay.js +169 -0
  97. package/framework/docs/examples/cloudflare-data-worker.js +102 -0
  98. package/framework/docs/examples/cloudflare-error-worker.js +228 -0
  99. package/framework/index.html +175 -0
  100. package/framework/js/app/AppActions.js +410 -0
  101. package/framework/js/app/AppState.js +225 -0
  102. package/framework/js/app/AppUI.js +616 -0
  103. package/framework/js/assessment/AssessmentActions.js +615 -0
  104. package/framework/js/assessment/AssessmentFactory.js +471 -0
  105. package/framework/js/assessment/AssessmentState.js +322 -0
  106. package/framework/js/assessment/AssessmentUI.js +451 -0
  107. package/framework/js/automation/api-engagement.js +196 -0
  108. package/framework/js/automation/api-interactions.js +167 -0
  109. package/framework/js/automation/api.js +242 -0
  110. package/framework/js/automation/index.js +41 -0
  111. package/framework/js/components/interactions/drag-drop.js +884 -0
  112. package/framework/js/components/interactions/fill-in.js +535 -0
  113. package/framework/js/components/interactions/hotspot.js +702 -0
  114. package/framework/js/components/interactions/interaction-base.js +511 -0
  115. package/framework/js/components/interactions/likert.js +301 -0
  116. package/framework/js/components/interactions/matching.js +699 -0
  117. package/framework/js/components/interactions/multiple-choice.js +377 -0
  118. package/framework/js/components/interactions/numeric.js +271 -0
  119. package/framework/js/components/interactions/sequencing.js +423 -0
  120. package/framework/js/components/interactions/true-false.js +241 -0
  121. package/framework/js/components/ui-components/accordion.js +442 -0
  122. package/framework/js/components/ui-components/alert.js +88 -0
  123. package/framework/js/components/ui-components/audio-player.js +1193 -0
  124. package/framework/js/components/ui-components/callout.js +121 -0
  125. package/framework/js/components/ui-components/carousel.js +145 -0
  126. package/framework/js/components/ui-components/checkbox-group.js +87 -0
  127. package/framework/js/components/ui-components/checklist.js +40 -0
  128. package/framework/js/components/ui-components/collapse.js +114 -0
  129. package/framework/js/components/ui-components/comparison.js +30 -0
  130. package/framework/js/components/ui-components/conditional-display.js +150 -0
  131. package/framework/js/components/ui-components/content-image.js +41 -0
  132. package/framework/js/components/ui-components/dropdown.js +262 -0
  133. package/framework/js/components/ui-components/embed-frame.js +274 -0
  134. package/framework/js/components/ui-components/features.js +33 -0
  135. package/framework/js/components/ui-components/flip-card.js +230 -0
  136. package/framework/js/components/ui-components/form-validator.js +76 -0
  137. package/framework/js/components/ui-components/hero.js +49 -0
  138. package/framework/js/components/ui-components/index.js +12 -0
  139. package/framework/js/components/ui-components/interactive-image.js +235 -0
  140. package/framework/js/components/ui-components/interactive-timeline.js +285 -0
  141. package/framework/js/components/ui-components/intro-cards.js +35 -0
  142. package/framework/js/components/ui-components/lightbox.js +652 -0
  143. package/framework/js/components/ui-components/modal.js +386 -0
  144. package/framework/js/components/ui-components/notifications.js +145 -0
  145. package/framework/js/components/ui-components/progress.js +88 -0
  146. package/framework/js/components/ui-components/quote.js +41 -0
  147. package/framework/js/components/ui-components/stats.js +33 -0
  148. package/framework/js/components/ui-components/steps.js +41 -0
  149. package/framework/js/components/ui-components/tabs.js +255 -0
  150. package/framework/js/components/ui-components/timeline.js +42 -0
  151. package/framework/js/components/ui-components/toggle-group.js +73 -0
  152. package/framework/js/components/ui-components/tooltip.js +458 -0
  153. package/framework/js/components/ui-components/value-display.js +133 -0
  154. package/framework/js/components/ui-components/video-player.js +686 -0
  155. package/framework/js/core/component-catalog.js +121 -0
  156. package/framework/js/core/event-bus.js +178 -0
  157. package/framework/js/core/interaction-catalog.js +149 -0
  158. package/framework/js/dev/runtime-linter.js +1725 -0
  159. package/framework/js/drivers/cmi5-driver.js +768 -0
  160. package/framework/js/drivers/driver-factory.js +77 -0
  161. package/framework/js/drivers/driver-interface.js +110 -0
  162. package/framework/js/drivers/http-driver-base.js +241 -0
  163. package/framework/js/drivers/lti-driver.js +508 -0
  164. package/framework/js/drivers/proxy-driver.js +444 -0
  165. package/framework/js/drivers/scorm-12-driver.js +560 -0
  166. package/framework/js/drivers/scorm-2004-driver.js +775 -0
  167. package/framework/js/drivers/scorm-driver-base.js +112 -0
  168. package/framework/js/engagement/engagement-manager.js +404 -0
  169. package/framework/js/engagement/engagement-progress.js +191 -0
  170. package/framework/js/engagement/engagement-trackers.js +215 -0
  171. package/framework/js/engagement/requirement-strategies.js +268 -0
  172. package/framework/js/main.js +727 -0
  173. package/framework/js/managers/accessibility-manager.js +499 -0
  174. package/framework/js/managers/assessment-manager.js +230 -0
  175. package/framework/js/managers/audio-manager.js +944 -0
  176. package/framework/js/managers/comment-manager.js +88 -0
  177. package/framework/js/managers/flag-manager.js +86 -0
  178. package/framework/js/managers/interaction-manager.js +254 -0
  179. package/framework/js/managers/interaction-registry.js +96 -0
  180. package/framework/js/managers/objective-manager.js +423 -0
  181. package/framework/js/managers/score-manager.js +441 -0
  182. package/framework/js/managers/video-manager.js +536 -0
  183. package/framework/js/navigation/Breadcrumbs.js +234 -0
  184. package/framework/js/navigation/NavigationActions.js +1132 -0
  185. package/framework/js/navigation/NavigationState.js +276 -0
  186. package/framework/js/navigation/NavigationUI.js +574 -0
  187. package/framework/js/navigation/document-gallery.js +357 -0
  188. package/framework/js/navigation/navigation-helpers.js +175 -0
  189. package/framework/js/navigation/navigation-validators.js +174 -0
  190. package/framework/js/state/index.js +8 -0
  191. package/framework/js/state/lms-connection.js +482 -0
  192. package/framework/js/state/lms-error-utils.js +58 -0
  193. package/framework/js/state/state-commits.js +200 -0
  194. package/framework/js/state/state-domains.js +86 -0
  195. package/framework/js/state/state-manager.js +502 -0
  196. package/framework/js/state/state-validation.js +311 -0
  197. package/framework/js/state/transaction-log.js +41 -0
  198. package/framework/js/state/xapi-statement-service.js +325 -0
  199. package/framework/js/utilities/access-control.js +99 -0
  200. package/framework/js/utilities/breakpoint-manager.js +315 -0
  201. package/framework/js/utilities/canvas-slide.js +35 -0
  202. package/framework/js/utilities/conditional-display.js +388 -0
  203. package/framework/js/utilities/course-channel.js +214 -0
  204. package/framework/js/utilities/course-helpers.js +420 -0
  205. package/framework/js/utilities/data-reporter.js +273 -0
  206. package/framework/js/utilities/error-reporter.js +313 -0
  207. package/framework/js/utilities/hotspot-helper.js +341 -0
  208. package/framework/js/utilities/icons.js +348 -0
  209. package/framework/js/utilities/logger.js +92 -0
  210. package/framework/js/utilities/markdown-renderer.js +45 -0
  211. package/framework/js/utilities/scroll-tracker.js +68 -0
  212. package/framework/js/utilities/ui-initializer.js +146 -0
  213. package/framework/js/utilities/utilities.js +293 -0
  214. package/framework/js/utilities/view-manager.js +227 -0
  215. package/framework/js/validation/html-validators.js +422 -0
  216. package/framework/js/validation/scorm-validators.js +438 -0
  217. package/framework/js/vendor/pipwerks.js +931 -0
  218. package/framework/scripts/generate-narration.js +629 -0
  219. package/framework/scripts/tts-providers/azure-provider.js +178 -0
  220. package/framework/scripts/tts-providers/base-provider.js +81 -0
  221. package/framework/scripts/tts-providers/deepgram-provider.js +135 -0
  222. package/framework/scripts/tts-providers/elevenlabs-provider.js +148 -0
  223. package/framework/scripts/tts-providers/google-provider.js +272 -0
  224. package/framework/scripts/tts-providers/index.js +158 -0
  225. package/framework/scripts/tts-providers/openai-provider.js +143 -0
  226. package/framework/version.json +63 -0
  227. package/lib/authoring-api.js +919 -0
  228. package/lib/build-linter.js +450 -0
  229. package/lib/build-packaging.js +186 -0
  230. package/lib/build.js +88 -0
  231. package/lib/cloud.js +691 -0
  232. package/lib/convert.js +341 -0
  233. package/lib/course-parser.js +936 -0
  234. package/lib/course-writer.js +258 -0
  235. package/lib/create.js +248 -0
  236. package/lib/css-index.js +237 -0
  237. package/lib/dev.js +51 -0
  238. package/lib/export-content.js +1246 -0
  239. package/lib/headless-browser.js +413 -0
  240. package/lib/import.js +377 -0
  241. package/lib/index.js +80 -0
  242. package/lib/info.js +79 -0
  243. package/lib/interaction-formatters.js +568 -0
  244. package/lib/manifest/cmi5-manifest.js +63 -0
  245. package/lib/manifest/lti-tool-config.js +53 -0
  246. package/lib/manifest/manifest-factory.js +99 -0
  247. package/lib/manifest/scorm-12-manifest.js +61 -0
  248. package/lib/manifest/scorm-2004-manifest.js +94 -0
  249. package/lib/manifest/scorm-proxy-manifest.js +104 -0
  250. package/lib/manifest-parser.js +96 -0
  251. package/lib/mcp-prompts.js +753 -0
  252. package/lib/mcp-server.js +316 -0
  253. package/lib/narration.js +53 -0
  254. package/lib/pdf-structure.js +142 -0
  255. package/lib/preview-export.js +231 -0
  256. package/lib/preview-routes-api.js +662 -0
  257. package/lib/preview-routes-editing.js +159 -0
  258. package/lib/preview-routes-lms.js +230 -0
  259. package/lib/preview-server.js +564 -0
  260. package/lib/project-utils.js +269 -0
  261. package/lib/proxy-templates/proxy.html +68 -0
  262. package/lib/proxy-templates/scorm-bridge.js +112 -0
  263. package/lib/scaffold.js +193 -0
  264. package/lib/schema-extractor.js +361 -0
  265. package/lib/slide-source-editor.js +586 -0
  266. package/lib/stub-player/app-viewer.js +195 -0
  267. package/lib/stub-player/app.js +370 -0
  268. package/lib/stub-player/catalog-panel.js +312 -0
  269. package/lib/stub-player/config-panel.js +1303 -0
  270. package/lib/stub-player/content-generator.js +586 -0
  271. package/lib/stub-player/content-viewer.js +173 -0
  272. package/lib/stub-player/debug-panel.js +420 -0
  273. package/lib/stub-player/edit-mode.js +922 -0
  274. package/lib/stub-player/edit-utils.js +400 -0
  275. package/lib/stub-player/header-bar.js +354 -0
  276. package/lib/stub-player/interaction-editor.js +210 -0
  277. package/lib/stub-player/interactions-panel.js +565 -0
  278. package/lib/stub-player/lms-api.js +1094 -0
  279. package/lib/stub-player/login-screen.js +74 -0
  280. package/lib/stub-player/outline-mode.js +689 -0
  281. package/lib/stub-player/styles/_assessments-panel.css +245 -0
  282. package/lib/stub-player/styles/_base.css +89 -0
  283. package/lib/stub-player/styles/_catalog-icons.css +96 -0
  284. package/lib/stub-player/styles/_catalog-panel.css +291 -0
  285. package/lib/stub-player/styles/_config-panel.css +636 -0
  286. package/lib/stub-player/styles/_content-viewer.css +834 -0
  287. package/lib/stub-player/styles/_debug-panel.css +576 -0
  288. package/lib/stub-player/styles/_edit-mode.css +128 -0
  289. package/lib/stub-player/styles/_header-bar.css +343 -0
  290. package/lib/stub-player/styles/_interaction-editor.css +140 -0
  291. package/lib/stub-player/styles/_interactions-panel.css +1038 -0
  292. package/lib/stub-player/styles/_login-screen.css +102 -0
  293. package/lib/stub-player/styles/_outline-mode.css +752 -0
  294. package/lib/stub-player/styles.css +15 -0
  295. package/lib/stub-player.js +160 -0
  296. package/lib/test-data-reporting.js +176 -0
  297. package/lib/test-error-reporting.js +146 -0
  298. package/lib/token.js +86 -0
  299. package/lib/upgrade.js +257 -0
  300. package/lib/validation-rules.js +517 -0
  301. package/lib/vite-plugin-content-discovery.js +296 -0
  302. package/package.json +108 -0
  303. package/schemas/XMLSchema.dtd +402 -0
  304. package/schemas/adlcp_v1p3.xsd +111 -0
  305. package/schemas/adlnav_v1p3.xsd +61 -0
  306. package/schemas/adlseq_v1p3.xsd +93 -0
  307. package/schemas/common/anyElement.xsd +27 -0
  308. package/schemas/common/dataTypes.xsd +138 -0
  309. package/schemas/common/elementNames.xsd +767 -0
  310. package/schemas/common/elementTypes.xsd +786 -0
  311. package/schemas/common/rootElement.xsd +31 -0
  312. package/schemas/common/vocabTypes.xsd +345 -0
  313. package/schemas/common/vocabValues.xsd +257 -0
  314. package/schemas/datatypes.dtd +203 -0
  315. package/schemas/ims_xml.xsd +35 -0
  316. package/schemas/imscp_v1p1.xsd +368 -0
  317. package/schemas/imsss_v1p0.xsd +67 -0
  318. package/schemas/imsss_v1p0auxresource.xsd +19 -0
  319. package/schemas/imsss_v1p0control.xsd +20 -0
  320. package/schemas/imsss_v1p0delivery.xsd +17 -0
  321. package/schemas/imsss_v1p0limit.xsd +47 -0
  322. package/schemas/imsss_v1p0objective.xsd +67 -0
  323. package/schemas/imsss_v1p0random.xsd +16 -0
  324. package/schemas/imsss_v1p0rollup.xsd +46 -0
  325. package/schemas/imsss_v1p0seqrule.xsd +108 -0
  326. package/schemas/imsss_v1p0util.xsd +94 -0
  327. package/schemas/license.txt +17 -0
  328. package/schemas/lom.xsd +102 -0
  329. package/schemas/lomCustom.xsd +62 -0
  330. package/schemas/lomLoose.xsd +62 -0
  331. package/schemas/lomStrict.xsd +62 -0
  332. package/schemas/xml.xsd +81 -0
  333. package/template/.env.example +92 -0
  334. package/template/course/assets/audio/example-intro.mp3 +0 -0
  335. package/template/course/assets/audio/example-ui-demo--compact-player.mp3 +0 -0
  336. package/template/course/assets/audio/example-ui-demo--demo-modal.mp3 +0 -0
  337. package/template/course/assets/audio/example-ui-demo--full-player.mp3 +0 -0
  338. package/template/course/assets/docs/example_md_1.md +39 -0
  339. package/template/course/assets/docs/example_md_2.md +41 -0
  340. package/template/course/assets/docs/example_pdf_1_thumbnail.png +0 -0
  341. package/template/course/assets/docs/example_pdf_2.pdf +0 -0
  342. package/template/course/assets/images/course-architecture.svg +36 -0
  343. package/template/course/assets/images/logo.svg +14 -0
  344. package/template/course/assets/widgets/counter-demo.html +190 -0
  345. package/template/course/assets/widgets/gravity-painter.html +384 -0
  346. package/template/course/course-config.js +539 -0
  347. package/template/course/icons.js +19 -0
  348. package/template/course/interactions/PLUGIN_GUIDE.md +97 -0
  349. package/template/course/slides/example-course-structure.js +138 -0
  350. package/template/course/slides/example-final-exam.js +144 -0
  351. package/template/course/slides/example-finishing.js +127 -0
  352. package/template/course/slides/example-interactions-showcase.js +615 -0
  353. package/template/course/slides/example-preview-tour.js +129 -0
  354. package/template/course/slides/example-remedial.js +143 -0
  355. package/template/course/slides/example-summary.js +103 -0
  356. package/template/course/slides/example-ui-showcase.js +1805 -0
  357. package/template/course/slides/example-welcome.js +123 -0
  358. package/template/course/slides/example-workflow.js +140 -0
  359. package/template/course/theme.css +165 -0
  360. package/template/eslint.config.js +47 -0
  361. package/template/package.json +28 -0
  362. package/template/vite.config.js +339 -0
@@ -0,0 +1,412 @@
1
+ /* ============================================================================
2
+ ENGAGEMENT INDICATOR - Circular progress, checklist, and progress bar
3
+ ============================================================================
4
+
5
+ PURPOSE: Track and display learner engagement and completion status
6
+
7
+ INCLUDES:
8
+ - Circular progress indicator in footer (SVG-based)
9
+ - Engagement checklist component
10
+ - Engagement progress bar
11
+ - Completion celebration state
12
+ - Dark mode and accessibility support
13
+
14
+ DEPENDENCIES:
15
+ - Requires: design-tokens.css (for CSS variables)
16
+
17
+ USED BY:
18
+ - Navigation footer (circular progress)
19
+ - Slide engagement tracking
20
+ - Completion indicators
21
+
22
+ AI DEBUGGING TIPS:
23
+ - Progress not animating? Check stroke-dashoffset CSS variable
24
+ - Checkmark not appearing? Verify .engagement-progress.complete class
25
+ - High contrast too thick? Check @media (prefers-contrast: high)
26
+ - Animation jerky? Check @media (prefers-reduced-motion: reduce)
27
+ - Progress circle not rotating? Verify SVG transform: rotate(-90deg)
28
+
29
+ STRUCTURE:
30
+ 1. Footer engagement indicator (45-60)
31
+ 2. SVG circle base (65-100)
32
+ 3. Progress animation (105-125)
33
+ 4. Checkmark (130-150)
34
+ 5. Engagement indicator component (155-200)
35
+ 6. Checklist (205-250)
36
+ 7. Progress bar (255-295)
37
+ 8. Completion state (300-320)
38
+ 9. Dark mode (325-340)
39
+ 10. High contrast (345-360)
40
+ 11. Reduced motion (365-385)
41
+ 12. Mobile adjustments (390-410)
42
+
43
+ ============================================================================ */
44
+
45
+ /* ============================================================================
46
+ ENGAGEMENT INDICATOR - CIRCULAR PROGRESS IN FOOTER
47
+ ============================================================================ */
48
+
49
+ .engagement-indicator-footer {
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ margin-left: var(--space-8);
54
+ position: relative;
55
+ opacity: 1;
56
+ }
57
+
58
+ .engagement-indicator-footer[hidden] {
59
+ display: none;
60
+ }
61
+
62
+ /* SVG Circular Progress */
63
+ .engagement-circle {
64
+ display: block;
65
+ transform: rotate(-90deg);
66
+ /* Start progress from top */
67
+ filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
68
+ }
69
+
70
+ /* Track (background circle) */
71
+ .engagement-track {
72
+ stroke: var(--border-strong);
73
+ }
74
+
75
+ /* Progress circle */
76
+ .engagement-progress {
77
+ stroke: var(--color-primary);
78
+ /* stroke-dasharray and stroke-dashoffset are set by JavaScript */
79
+ /* Longer duration (0.8s) for smoother visual updates when timer ticks every second */
80
+ transition: stroke-dashoffset 0.8s cubic-bezier(0.4, 0, 0.2, 1),
81
+ stroke 0.3s ease;
82
+ transform-origin: center;
83
+ }
84
+
85
+ /* When complete, change color and add subtle animation */
86
+ .engagement-progress.complete {
87
+ stroke: var(--color-success);
88
+ animation: pulse-success 0.6s ease-out;
89
+ }
90
+
91
+ @keyframes pulse-success {
92
+ 0% {
93
+ opacity: 1;
94
+ }
95
+
96
+ 50% {
97
+ opacity: 0.7;
98
+ filter: drop-shadow(0 0 6px var(--color-success));
99
+ }
100
+
101
+ 100% {
102
+ opacity: 1;
103
+ }
104
+ }
105
+
106
+ /* Checkmark */
107
+ .engagement-checkmark {
108
+ fill: var(--color-success);
109
+ font-weight: bold;
110
+ opacity: 0;
111
+ transition: opacity 0.3s ease 0.2s;
112
+ /* Delay checkmark appearance */
113
+ pointer-events: none;
114
+ transform: rotate(90deg);
115
+ /* Counter-rotate the checkmark since parent SVG is rotated -90deg */
116
+ transform-origin: center;
117
+ }
118
+
119
+ /* ============================================================================
120
+ ENGAGEMENT INDICATOR COMPONENT (Slide-level tracking)
121
+ ============================================================================ */
122
+
123
+ .engagement-indicator {
124
+ background: var(--bg-surface);
125
+ border: 1px solid var(--border-default);
126
+ border-radius: var(--radius-lg);
127
+ padding: var(--space-4);
128
+ margin: var(--space-4) 0;
129
+ box-shadow: var(--shadow-sm);
130
+ }
131
+
132
+ .engagement-indicator--top {
133
+ margin-bottom: var(--space-6);
134
+ }
135
+
136
+ .engagement-indicator--bottom {
137
+ margin-top: var(--space-6);
138
+ }
139
+
140
+ /* ============================================================================
141
+ PROGRESS BAR
142
+ ============================================================================ */
143
+
144
+ .engagement-progress-bar {
145
+ position: relative;
146
+ width: 100%;
147
+ height: 32px;
148
+ background: var(--bg-muted);
149
+ border-radius: var(--radius-md);
150
+ overflow: hidden;
151
+ margin-bottom: var(--space-3);
152
+ }
153
+
154
+ .engagement-progress-fill {
155
+ height: 100%;
156
+ width: var(--progress, 0%);
157
+ background: linear-gradient(90deg,
158
+ var(--color-primary),
159
+ var(--color-secondary));
160
+ transition: width 0.5s ease;
161
+ border-radius: var(--radius-md);
162
+ }
163
+
164
+ .engagement-progress-text {
165
+ position: absolute;
166
+ top: 50%;
167
+ left: 50%;
168
+ transform: translate(-50%, -50%);
169
+ font-size: var(--font-size-sm);
170
+ font-weight: var(--font-weight-semibold);
171
+ color: var(--text-primary);
172
+ text-shadow: 0 1px 2px rgba(255, 255, 255, 0.8);
173
+ z-index: 1;
174
+ }
175
+
176
+ /* ============================================================================
177
+ CHECKLIST
178
+ ============================================================================ */
179
+
180
+ .engagement-checklist {
181
+ list-style: none;
182
+ padding: 0;
183
+ margin: 0;
184
+ display: flex;
185
+ flex-direction: column;
186
+ gap: var(--space-2);
187
+ }
188
+
189
+ .engagement-checklist-item {
190
+ display: flex;
191
+ align-items: center;
192
+ gap: var(--space-2);
193
+ padding: var(--space-2);
194
+ border-radius: var(--radius-md);
195
+ transition: background var(--transition-fast);
196
+ }
197
+
198
+ .engagement-checklist-item.incomplete {
199
+ color: var(--text-muted);
200
+ }
201
+
202
+ .engagement-checklist-item.complete {
203
+ color: var(--color-success);
204
+ font-weight: var(--font-weight-medium);
205
+ }
206
+
207
+ .engagement-icon {
208
+ flex-shrink: 0;
209
+ width: 20px;
210
+ height: 20px;
211
+ display: flex;
212
+ align-items: center;
213
+ justify-content: center;
214
+ font-size: var(--font-size-lg);
215
+ line-height: 1;
216
+ }
217
+
218
+ .engagement-checklist-item.incomplete .engagement-icon {
219
+ color: var(--text-muted);
220
+ }
221
+
222
+ .engagement-checklist-item.complete .engagement-icon {
223
+ color: var(--color-success);
224
+ }
225
+
226
+ .engagement-label {
227
+ flex: 1;
228
+ font-size: var(--font-size-sm);
229
+ }
230
+
231
+ /* ============================================================================
232
+ COMPLETION STATE
233
+ ============================================================================ */
234
+
235
+ .engagement-indicator.engagement-complete {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: var(--space-3);
239
+ padding: var(--space-3);
240
+ background: var(--color-success-alpha-10);
241
+ border: 1px solid var(--color-success-alpha-20);
242
+ border-radius: var(--radius-md);
243
+ color: var(--color-success);
244
+ font-weight: var(--font-weight-semibold);
245
+ }
246
+
247
+ .engagement-complete .engagement-icon {
248
+ font-size: var(--font-size-xl);
249
+ }
250
+
251
+ /* ============================================================================
252
+ DARK MODE SUPPORT
253
+ ============================================================================ */
254
+
255
+ [data-theme="dark"] .engagement-track {
256
+ stroke: var(--border-strong);
257
+ }
258
+
259
+ [data-theme="dark"] .engagement-circle {
260
+ filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.3));
261
+ }
262
+
263
+ /* ============================================================================
264
+ HIGH CONTRAST MODE
265
+ ============================================================================ */
266
+
267
+ [data-high-contrast="true"] .engagement-progress {
268
+ stroke-width: 4;
269
+ }
270
+
271
+ [data-high-contrast="true"] .engagement-track {
272
+ stroke-width: 4;
273
+ opacity: 0.8;
274
+ }
275
+
276
+ /* ============================================================================
277
+ REDUCED MOTION PREFERENCE
278
+ ============================================================================ */
279
+
280
+ @media (prefers-reduced-motion: reduce) {
281
+ .engagement-progress {
282
+ transition: none;
283
+ }
284
+
285
+ .engagement-checkmark {
286
+ transition: none;
287
+ }
288
+
289
+ .engagement-progress.complete {
290
+ animation: none;
291
+ }
292
+ }
293
+
294
+ /* ============================================================================
295
+ MOBILE ADJUSTMENTS
296
+ ============================================================================ */
297
+
298
+ /* Hide footer progress indicator on mobile - next button disabled state
299
+ provides sufficient gating feedback without consuming footer space */
300
+ @media (max-width: 767px) {
301
+ .engagement-indicator-footer {
302
+ display: none;
303
+ }
304
+ }
305
+
306
+ /* Tablet adjustments - slightly smaller */
307
+ @media (max-width: 768px) {
308
+ .engagement-circle {
309
+ width: 28px;
310
+ height: 28px;
311
+ }
312
+
313
+ .engagement-indicator-footer {
314
+ margin-left: var(--space-2);
315
+ }
316
+
317
+ .engagement-indicator {
318
+ padding: var(--space-3);
319
+ }
320
+
321
+ .engagement-progress-bar {
322
+ height: 28px;
323
+ }
324
+
325
+ .engagement-progress-text {
326
+ font-size: var(--font-size-xs);
327
+ }
328
+
329
+ .engagement-label {
330
+ font-size: var(--font-size-xs);
331
+ }
332
+ }
333
+
334
+ /* Very small screens - even more compact */
335
+ @media (max-width: 480px) {
336
+ .engagement-circle {
337
+ width: 24px;
338
+ height: 24px;
339
+ }
340
+
341
+ .engagement-checkmark {
342
+ font-size: var(--font-size-sm);
343
+ }
344
+ }
345
+
346
+ /* ============================================================================
347
+ DATA-LAYOUT VARIANTS
348
+ ============================================================================
349
+ Engagement styling controlled by data-layout attribute on <html>.
350
+ These styles are used by the layout system (framework/css/layouts/).
351
+ ============================================================================ */
352
+
353
+ /* -----------------------------------------------------------------------------
354
+ Article & Focused: Progressive gating border indicator on next button
355
+ -----------------------------------------------------------------------------
356
+ The button border shows progress via conic-gradient.
357
+ Uses CSS custom property --engagement-progress (0-100) set by JS.
358
+ ----------------------------------------------------------------------------- */
359
+
360
+ /* Hide the old circular engagement indicator - we use the button ring instead */
361
+ [data-layout="article"] .engagement-indicator-footer,
362
+ [data-layout="focused"] .engagement-indicator-footer {
363
+ display: none;
364
+ }
365
+
366
+ /* Hide engagement indicator in presentation mode */
367
+ [data-layout="presentation"] #engagement-indicator {
368
+ display: none;
369
+ }
370
+
371
+ /* Gated state: border becomes the progress indicator */
372
+ /* Uses !important to override global disabled button styles in buttons.css */
373
+ [data-layout="article"] footer #nextBtn.gated,
374
+ [data-layout="article"] footer #nextBtn.gated:disabled,
375
+ [data-layout="focused"] footer #nextBtn.gated,
376
+ [data-layout="focused"] footer #nextBtn.gated:disabled {
377
+ border: var(--border-width-sm, 1.5px) solid transparent !important;
378
+ background:
379
+ linear-gradient(var(--bg-inset), var(--bg-inset)) padding-box,
380
+ conic-gradient(from 0deg,
381
+ var(--color-primary) calc(var(--engagement-progress, 0) * 1%),
382
+ var(--color-gray-300) calc(var(--engagement-progress, 0) * 1%)) border-box !important;
383
+ transition: background 0.3s ease-out;
384
+ opacity: 1 !important;
385
+ }
386
+
387
+ /* Complete state: full green border with brief pulse animation */
388
+ @keyframes border-complete {
389
+ 0% {
390
+ transform: scale(1);
391
+ }
392
+
393
+ 30% {
394
+ transform: scale(1.05);
395
+ }
396
+
397
+ 100% {
398
+ transform: scale(1);
399
+ }
400
+ }
401
+
402
+ [data-layout="article"] footer #nextBtn.gated.engagement-complete,
403
+ [data-layout="article"] footer #nextBtn.gated.engagement-complete:disabled,
404
+ [data-layout="focused"] footer #nextBtn.gated.engagement-complete,
405
+ [data-layout="focused"] footer #nextBtn.gated.engagement-complete:disabled {
406
+ background:
407
+ linear-gradient(var(--bg-inset), var(--bg-inset)) padding-box,
408
+ conic-gradient(from 0deg,
409
+ var(--color-success) 100%,
410
+ var(--color-success) 100%) border-box !important;
411
+ animation: border-complete 0.4s ease-out;
412
+ }
@@ -0,0 +1,35 @@
1
+ /* ========================================
2
+ UI COMPONENT: Feature Showcase
3
+ Use for: Highlighting 3-4 key features
4
+ ======================================== */
5
+ [data-component="features"] {
6
+ display: flex;
7
+ flex-wrap: wrap;
8
+ justify-content: center;
9
+ gap: var(--space-4);
10
+ }
11
+
12
+ [data-component="features"] .feature-item {
13
+ text-align: center;
14
+ padding: var(--space-4);
15
+ flex: 0 1 200px;
16
+ max-width: 280px;
17
+ }
18
+
19
+ [data-component="features"] .feature-icon {
20
+ font-size: 3rem;
21
+ margin-bottom: var(--space-3);
22
+ display: block;
23
+ color: var(--color-primary);
24
+ }
25
+
26
+ [data-component="features"] .feature-item h3 {
27
+ margin-bottom: var(--space-2);
28
+ }
29
+
30
+ @media (max-width: 640px) {
31
+ [data-component="features"] .feature-item {
32
+ flex: 1 1 100%;
33
+ max-width: 100%;
34
+ }
35
+ }
@@ -0,0 +1,253 @@
1
+ /* ============================================================================
2
+ FLIP CARDS - Interactive 3D Flip Card Component
3
+ ============================================================================
4
+
5
+ PURPOSE: Interactive cards that reveal content on hover/focus
6
+
7
+ INCLUDES:
8
+ - Base flip card structure
9
+ - Front and back face styling
10
+ - 3D transform animations
11
+ - Accessibility support (focus-within)
12
+
13
+ DEPENDENCIES:
14
+ - design-tokens.css
15
+
16
+ USAGE:
17
+ <div class="flip-card">
18
+ <div class="flip-card-inner">
19
+ <div class="flip-card-front">
20
+ <!-- Front Content -->
21
+ </div>
22
+ <div class="flip-card-back">
23
+ <!-- Back Content -->
24
+ </div>
25
+ </div>
26
+ </div>
27
+
28
+ ============================================================================ */
29
+
30
+ .flip-card {
31
+ background-color: transparent;
32
+ perspective: 1000px;
33
+ width: 100%; /* Fill grid cell or container width */
34
+ min-width: 0; /* Allow shrinking in flex/grid contexts */
35
+ min-height: var(--size-card-min-height);
36
+ cursor: pointer; /* Indicate interactivity */
37
+ }
38
+
39
+ /* Flip cards in grid layouts need explicit sizing since content is absolutely positioned.
40
+ Without min-width, grid columns collapse to 0px because absolutely positioned children
41
+ contribute no intrinsic size. The width/height: 100% ensures cards fill their grid cell. */
42
+ .card-grid .flip-card,
43
+ .card-grid-2 .flip-card,
44
+ .card-grid-3 .flip-card {
45
+ min-width: 200px; /* Establish minimum for grid sizing */
46
+ width: 100%; /* Fill the entire grid cell width */
47
+ height: 100%; /* Fill the entire grid cell height (for equal row heights) */
48
+ }
49
+
50
+ .flip-card-inner {
51
+ display: grid; /* Grid allows both faces to contribute to height */
52
+ width: 100%;
53
+ height: 100%; /* Fill parent flip-card height */
54
+ min-height: var(--size-card-min-height);
55
+ text-align: center;
56
+ transition: transform 0.6s cubic-bezier(0.4, 0.0, 0.2, 1);
57
+ transform-style: preserve-3d;
58
+ }
59
+
60
+ /* Flip when .is-flipped class is present (toggled via JS) */
61
+ .flip-card.is-flipped .flip-card-inner {
62
+ transform: rotateY(180deg);
63
+ }
64
+
65
+ /* Both faces occupy the same grid cell, so the taller one sets the height */
66
+ .flip-card-front,
67
+ .flip-card-back {
68
+ grid-area: 1 / 1; /* Both in same cell */
69
+ width: 100%;
70
+ box-sizing: border-box;
71
+ -webkit-backface-visibility: hidden;
72
+ backface-visibility: hidden;
73
+ border-radius: var(--radius-lg);
74
+ padding: var(--space-6);
75
+ box-shadow: var(--shadow-md);
76
+ display: flex;
77
+ flex-direction: column;
78
+ justify-content: center;
79
+ align-items: center;
80
+ border: var(--border-width-thin) solid var(--color-gray-300);
81
+ background-color: var(--bg-elevated);
82
+ }
83
+
84
+ .flip-card-front {
85
+ color: var(--color-text);
86
+ z-index: 2;
87
+ }
88
+
89
+ .flip-card-back {
90
+ transform: rotateY(180deg);
91
+ background-color: var(--color-primary);
92
+ color: var(--color-white);
93
+ border-color: var(--color-primary);
94
+ z-index: 1;
95
+ }
96
+
97
+ /* Flip card content container - handles text alignment */
98
+ .flip-card-content {
99
+ width: 100%;
100
+ text-align: left; /* Default to left-aligned text for readability */
101
+ }
102
+
103
+ /* Front face content typically centered */
104
+ .flip-card-front .flip-card-content {
105
+ text-align: center;
106
+ }
107
+
108
+ /* Back face keeps left alignment for lists/paragraphs but centers the block */
109
+ .flip-card-back .flip-card-content {
110
+ text-align: center; /* Center headings */
111
+ }
112
+
113
+ /* Lists and paragraphs on back should be left-aligned for readability */
114
+ .flip-card-back .flip-card-content ul,
115
+ .flip-card-back .flip-card-content ol,
116
+ .flip-card-back .flip-card-content p:not(:first-child) {
117
+ text-align: left;
118
+ }
119
+
120
+ /* High contrast text for back of card - inherit white for all text elements */
121
+ .flip-card-back .flip-card-title,
122
+ .flip-card-back .flip-card-text,
123
+ .flip-card-back h1,
124
+ .flip-card-back h2,
125
+ .flip-card-back h3,
126
+ .flip-card-back h4,
127
+ .flip-card-back h5,
128
+ .flip-card-back h6,
129
+ .flip-card-back p,
130
+ .flip-card-back li,
131
+ .flip-card-back strong,
132
+ .flip-card-back b {
133
+ color: inherit;
134
+ }
135
+
136
+ /* Ensure strong/bold text stays bold white, not theme colors */
137
+ .flip-card-back strong,
138
+ .flip-card-back b {
139
+ font-weight: var(--font-weight-bold);
140
+ }
141
+
142
+ /* Styled list markers should also be white on dark backgrounds */
143
+ .flip-card-back .list-styled li::marker,
144
+ .flip-card-back .list-numbered li::marker {
145
+ color: var(--color-white);
146
+ }
147
+
148
+ /* Callouts inside flip card back need special handling */
149
+ .flip-card-back .callout {
150
+ --callout-bg: rgba(255, 255, 255, 0.15);
151
+ --callout-border: rgba(255, 255, 255, 0.3);
152
+ background-color: var(--callout-bg);
153
+ border-color: var(--callout-border);
154
+ }
155
+
156
+ .flip-card-back .callout p,
157
+ .flip-card-back .callout strong {
158
+ color: var(--color-white);
159
+ }
160
+
161
+ /* Warning callout gets a slightly different treatment for visibility */
162
+ .flip-card-back .callout-warning {
163
+ --callout-bg: rgba(255, 193, 7, 0.2);
164
+ --callout-border: rgba(255, 193, 7, 0.5);
165
+ }
166
+
167
+ /* Variant: Light Back (Alternative for better readability) */
168
+ .flip-card-back.bg-light {
169
+ background-color: var(--bg-subtle);
170
+ color: var(--color-text);
171
+ border-color: var(--color-gray-300);
172
+ }
173
+ .flip-card-back.bg-light .flip-card-title,
174
+ .flip-card-back.bg-light .flip-card-text,
175
+ .flip-card-back.bg-light h1,
176
+ .flip-card-back.bg-light h2,
177
+ .flip-card-back.bg-light h3,
178
+ .flip-card-back.bg-light h4,
179
+ .flip-card-back.bg-light p,
180
+ .flip-card-back.bg-light li,
181
+ .flip-card-back.bg-light strong {
182
+ color: var(--color-text);
183
+ }
184
+
185
+ .flip-card-back.bg-light .list-styled li::marker,
186
+ .flip-card-back.bg-light .list-numbered li::marker {
187
+ color: var(--color-primary);
188
+ }
189
+
190
+ .flip-card-back.bg-light .callout {
191
+ --callout-bg: initial;
192
+ --callout-border: initial;
193
+ background-color: var(--callout-bg);
194
+ border-color: var(--callout-border);
195
+ }
196
+
197
+ /* Variant: Subtle/Light Semantic Backgrounds - Override white text with dark text */
198
+ .flip-card-back.bg-primary-subtle,
199
+ .flip-card-back.bg-secondary-subtle,
200
+ .flip-card-back.bg-success-subtle,
201
+ .flip-card-back.bg-warning-subtle,
202
+ .flip-card-back.bg-danger-subtle,
203
+ .flip-card-back.bg-info-subtle {
204
+ color: var(--color-text);
205
+ border-color: var(--color-gray-300);
206
+ }
207
+
208
+ .flip-card-back.bg-primary-subtle .flip-card-title,
209
+ .flip-card-back.bg-primary-subtle .flip-card-text,
210
+ .flip-card-back.bg-secondary-subtle .flip-card-title,
211
+ .flip-card-back.bg-secondary-subtle .flip-card-text,
212
+ .flip-card-back.bg-success-subtle .flip-card-title,
213
+ .flip-card-back.bg-success-subtle .flip-card-text,
214
+ .flip-card-back.bg-warning-subtle .flip-card-title,
215
+ .flip-card-back.bg-warning-subtle .flip-card-text,
216
+ .flip-card-back.bg-danger-subtle .flip-card-title,
217
+ .flip-card-back.bg-danger-subtle .flip-card-text,
218
+ .flip-card-back.bg-info-subtle .flip-card-title,
219
+ .flip-card-back.bg-info-subtle .flip-card-text {
220
+ color: var(--color-text);
221
+ text-shadow: none;
222
+ }
223
+
224
+ /* Variant: Secondary Color */
225
+ .flip-card-back.bg-secondary {
226
+ background-color: var(--color-secondary);
227
+ border-color: var(--color-secondary);
228
+ color: var(--color-text); /* Secondary is usually light/yellow */
229
+ }
230
+
231
+ /* Variant: Dark Color */
232
+ .flip-card-back.bg-dark {
233
+ background-color: var(--color-gray-900);
234
+ border-color: var(--color-gray-900);
235
+ }
236
+
237
+ /* Content styling helpers */
238
+ .flip-card-icon {
239
+ font-size: 3rem;
240
+ margin-bottom: var(--space-4);
241
+ display: block;
242
+ }
243
+
244
+ .flip-card-title {
245
+ font-size: var(--font-size-lg);
246
+ font-weight: var(--font-weight-bold);
247
+ margin-bottom: var(--space-2);
248
+ }
249
+
250
+ .flip-card-text {
251
+ font-size: var(--font-size-md);
252
+ line-height: 1.5;
253
+ }