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.
- package/LICENSE +21 -0
- package/README.md +322 -0
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/bin/cli.js +331 -0
- package/framework/assets/logo-coursecode-black.svg +14 -0
- package/framework/assets/logo-coursecode-white.svg +14 -0
- package/framework/assets/logo-coursecode.svg +14 -0
- package/framework/css/01-base.css +160 -0
- package/framework/css/02-layout.css +499 -0
- package/framework/css/accessibility.css +834 -0
- package/framework/css/components/accordions.css +710 -0
- package/framework/css/components/assessments.css +520 -0
- package/framework/css/components/audio-player.css +570 -0
- package/framework/css/components/badges.css +80 -0
- package/framework/css/components/breadcrumbs.css +87 -0
- package/framework/css/components/buttons.css +707 -0
- package/framework/css/components/callouts.css +1280 -0
- package/framework/css/components/cards.css +475 -0
- package/framework/css/components/carousel.css +193 -0
- package/framework/css/components/checkbox-group.css +123 -0
- package/framework/css/components/checklist.css +203 -0
- package/framework/css/components/collapse.css +96 -0
- package/framework/css/components/comparison.css +33 -0
- package/framework/css/components/content-image.css +36 -0
- package/framework/css/components/document-gallery.css +425 -0
- package/framework/css/components/dropdown.css +115 -0
- package/framework/css/components/embed-frame.css +142 -0
- package/framework/css/components/engagement.css +412 -0
- package/framework/css/components/features.css +35 -0
- package/framework/css/components/flip-cards.css +253 -0
- package/framework/css/components/footer.css +353 -0
- package/framework/css/components/forms.css +294 -0
- package/framework/css/components/hero.css +216 -0
- package/framework/css/components/images.css +528 -0
- package/framework/css/components/interactive-timeline.css +274 -0
- package/framework/css/components/intro-cards.css +30 -0
- package/framework/css/components/lightbox.css +666 -0
- package/framework/css/components/loading.css +65 -0
- package/framework/css/components/modals.css +235 -0
- package/framework/css/components/notifications.css +107 -0
- package/framework/css/components/quote.css +150 -0
- package/framework/css/components/sidebar.css +684 -0
- package/framework/css/components/slide-header.css +52 -0
- package/framework/css/components/spinner.css +62 -0
- package/framework/css/components/stats.css +44 -0
- package/framework/css/components/steps.css +232 -0
- package/framework/css/components/tables.css +90 -0
- package/framework/css/components/tabs.css +347 -0
- package/framework/css/components/timeline.css +154 -0
- package/framework/css/components/toggle.css +95 -0
- package/framework/css/components/tooltip.css +226 -0
- package/framework/css/components/video-player.css +438 -0
- package/framework/css/design-tokens.css +707 -0
- package/framework/css/framework.css +86 -0
- package/framework/css/interactions/accessibility.css +75 -0
- package/framework/css/interactions/base.css +92 -0
- package/framework/css/interactions/drag-drop.css +295 -0
- package/framework/css/interactions/fill-in-the-blank.css +236 -0
- package/framework/css/interactions/hotspots.css +69 -0
- package/framework/css/interactions/index.css +45 -0
- package/framework/css/interactions/interactive-image.css +359 -0
- package/framework/css/interactions/likert.css +126 -0
- package/framework/css/interactions/matching.css +354 -0
- package/framework/css/interactions/numeric-input.css +78 -0
- package/framework/css/interactions/sequencing.css +378 -0
- package/framework/css/interactions/true-false.css +177 -0
- package/framework/css/layouts/article.css +258 -0
- package/framework/css/layouts/base.css +30 -0
- package/framework/css/layouts/canvas.css +38 -0
- package/framework/css/layouts/focused.css +236 -0
- package/framework/css/layouts/index.css +29 -0
- package/framework/css/layouts/presentation.css +191 -0
- package/framework/css/layouts/traditional.css +52 -0
- package/framework/css/responsive.css +439 -0
- package/framework/css/utilities/accessibility-utils.css +59 -0
- package/framework/css/utilities/animations.css +419 -0
- package/framework/css/utilities/borders.css +72 -0
- package/framework/css/utilities/colors.css +76 -0
- package/framework/css/utilities/container.css +46 -0
- package/framework/css/utilities/decorative.css +442 -0
- package/framework/css/utilities/display.css +257 -0
- package/framework/css/utilities/flexbox.css +80 -0
- package/framework/css/utilities/grid.css +69 -0
- package/framework/css/utilities/icons.css +534 -0
- package/framework/css/utilities/lists.css +190 -0
- package/framework/css/utilities/spacing.css +167 -0
- package/framework/css/utilities/tables.css +81 -0
- package/framework/css/utilities/typography.css +159 -0
- package/framework/css/utilities/visibility.css +117 -0
- package/framework/docs/COURSE_AUTHORING_GUIDE.md +1773 -0
- package/framework/docs/COURSE_OUTLINE_GUIDE.md +725 -0
- package/framework/docs/COURSE_OUTLINE_TEMPLATE.md +161 -0
- package/framework/docs/DATA_MODEL.md +409 -0
- package/framework/docs/FRAMEWORK_GUIDE.md +1088 -0
- package/framework/docs/USER_GUIDE.md +583 -0
- package/framework/docs/examples/cloudflare-channel-relay.js +169 -0
- package/framework/docs/examples/cloudflare-data-worker.js +102 -0
- package/framework/docs/examples/cloudflare-error-worker.js +228 -0
- package/framework/index.html +175 -0
- package/framework/js/app/AppActions.js +410 -0
- package/framework/js/app/AppState.js +225 -0
- package/framework/js/app/AppUI.js +616 -0
- package/framework/js/assessment/AssessmentActions.js +615 -0
- package/framework/js/assessment/AssessmentFactory.js +471 -0
- package/framework/js/assessment/AssessmentState.js +322 -0
- package/framework/js/assessment/AssessmentUI.js +451 -0
- package/framework/js/automation/api-engagement.js +196 -0
- package/framework/js/automation/api-interactions.js +167 -0
- package/framework/js/automation/api.js +242 -0
- package/framework/js/automation/index.js +41 -0
- package/framework/js/components/interactions/drag-drop.js +884 -0
- package/framework/js/components/interactions/fill-in.js +535 -0
- package/framework/js/components/interactions/hotspot.js +702 -0
- package/framework/js/components/interactions/interaction-base.js +511 -0
- package/framework/js/components/interactions/likert.js +301 -0
- package/framework/js/components/interactions/matching.js +699 -0
- package/framework/js/components/interactions/multiple-choice.js +377 -0
- package/framework/js/components/interactions/numeric.js +271 -0
- package/framework/js/components/interactions/sequencing.js +423 -0
- package/framework/js/components/interactions/true-false.js +241 -0
- package/framework/js/components/ui-components/accordion.js +442 -0
- package/framework/js/components/ui-components/alert.js +88 -0
- package/framework/js/components/ui-components/audio-player.js +1193 -0
- package/framework/js/components/ui-components/callout.js +121 -0
- package/framework/js/components/ui-components/carousel.js +145 -0
- package/framework/js/components/ui-components/checkbox-group.js +87 -0
- package/framework/js/components/ui-components/checklist.js +40 -0
- package/framework/js/components/ui-components/collapse.js +114 -0
- package/framework/js/components/ui-components/comparison.js +30 -0
- package/framework/js/components/ui-components/conditional-display.js +150 -0
- package/framework/js/components/ui-components/content-image.js +41 -0
- package/framework/js/components/ui-components/dropdown.js +262 -0
- package/framework/js/components/ui-components/embed-frame.js +274 -0
- package/framework/js/components/ui-components/features.js +33 -0
- package/framework/js/components/ui-components/flip-card.js +230 -0
- package/framework/js/components/ui-components/form-validator.js +76 -0
- package/framework/js/components/ui-components/hero.js +49 -0
- package/framework/js/components/ui-components/index.js +12 -0
- package/framework/js/components/ui-components/interactive-image.js +235 -0
- package/framework/js/components/ui-components/interactive-timeline.js +285 -0
- package/framework/js/components/ui-components/intro-cards.js +35 -0
- package/framework/js/components/ui-components/lightbox.js +652 -0
- package/framework/js/components/ui-components/modal.js +386 -0
- package/framework/js/components/ui-components/notifications.js +145 -0
- package/framework/js/components/ui-components/progress.js +88 -0
- package/framework/js/components/ui-components/quote.js +41 -0
- package/framework/js/components/ui-components/stats.js +33 -0
- package/framework/js/components/ui-components/steps.js +41 -0
- package/framework/js/components/ui-components/tabs.js +255 -0
- package/framework/js/components/ui-components/timeline.js +42 -0
- package/framework/js/components/ui-components/toggle-group.js +73 -0
- package/framework/js/components/ui-components/tooltip.js +458 -0
- package/framework/js/components/ui-components/value-display.js +133 -0
- package/framework/js/components/ui-components/video-player.js +686 -0
- package/framework/js/core/component-catalog.js +121 -0
- package/framework/js/core/event-bus.js +178 -0
- package/framework/js/core/interaction-catalog.js +149 -0
- package/framework/js/dev/runtime-linter.js +1725 -0
- package/framework/js/drivers/cmi5-driver.js +768 -0
- package/framework/js/drivers/driver-factory.js +77 -0
- package/framework/js/drivers/driver-interface.js +110 -0
- package/framework/js/drivers/http-driver-base.js +241 -0
- package/framework/js/drivers/lti-driver.js +508 -0
- package/framework/js/drivers/proxy-driver.js +444 -0
- package/framework/js/drivers/scorm-12-driver.js +560 -0
- package/framework/js/drivers/scorm-2004-driver.js +775 -0
- package/framework/js/drivers/scorm-driver-base.js +112 -0
- package/framework/js/engagement/engagement-manager.js +404 -0
- package/framework/js/engagement/engagement-progress.js +191 -0
- package/framework/js/engagement/engagement-trackers.js +215 -0
- package/framework/js/engagement/requirement-strategies.js +268 -0
- package/framework/js/main.js +727 -0
- package/framework/js/managers/accessibility-manager.js +499 -0
- package/framework/js/managers/assessment-manager.js +230 -0
- package/framework/js/managers/audio-manager.js +944 -0
- package/framework/js/managers/comment-manager.js +88 -0
- package/framework/js/managers/flag-manager.js +86 -0
- package/framework/js/managers/interaction-manager.js +254 -0
- package/framework/js/managers/interaction-registry.js +96 -0
- package/framework/js/managers/objective-manager.js +423 -0
- package/framework/js/managers/score-manager.js +441 -0
- package/framework/js/managers/video-manager.js +536 -0
- package/framework/js/navigation/Breadcrumbs.js +234 -0
- package/framework/js/navigation/NavigationActions.js +1132 -0
- package/framework/js/navigation/NavigationState.js +276 -0
- package/framework/js/navigation/NavigationUI.js +574 -0
- package/framework/js/navigation/document-gallery.js +357 -0
- package/framework/js/navigation/navigation-helpers.js +175 -0
- package/framework/js/navigation/navigation-validators.js +174 -0
- package/framework/js/state/index.js +8 -0
- package/framework/js/state/lms-connection.js +482 -0
- package/framework/js/state/lms-error-utils.js +58 -0
- package/framework/js/state/state-commits.js +200 -0
- package/framework/js/state/state-domains.js +86 -0
- package/framework/js/state/state-manager.js +502 -0
- package/framework/js/state/state-validation.js +311 -0
- package/framework/js/state/transaction-log.js +41 -0
- package/framework/js/state/xapi-statement-service.js +325 -0
- package/framework/js/utilities/access-control.js +99 -0
- package/framework/js/utilities/breakpoint-manager.js +315 -0
- package/framework/js/utilities/canvas-slide.js +35 -0
- package/framework/js/utilities/conditional-display.js +388 -0
- package/framework/js/utilities/course-channel.js +214 -0
- package/framework/js/utilities/course-helpers.js +420 -0
- package/framework/js/utilities/data-reporter.js +273 -0
- package/framework/js/utilities/error-reporter.js +313 -0
- package/framework/js/utilities/hotspot-helper.js +341 -0
- package/framework/js/utilities/icons.js +348 -0
- package/framework/js/utilities/logger.js +92 -0
- package/framework/js/utilities/markdown-renderer.js +45 -0
- package/framework/js/utilities/scroll-tracker.js +68 -0
- package/framework/js/utilities/ui-initializer.js +146 -0
- package/framework/js/utilities/utilities.js +293 -0
- package/framework/js/utilities/view-manager.js +227 -0
- package/framework/js/validation/html-validators.js +422 -0
- package/framework/js/validation/scorm-validators.js +438 -0
- package/framework/js/vendor/pipwerks.js +931 -0
- package/framework/scripts/generate-narration.js +629 -0
- package/framework/scripts/tts-providers/azure-provider.js +178 -0
- package/framework/scripts/tts-providers/base-provider.js +81 -0
- package/framework/scripts/tts-providers/deepgram-provider.js +135 -0
- package/framework/scripts/tts-providers/elevenlabs-provider.js +148 -0
- package/framework/scripts/tts-providers/google-provider.js +272 -0
- package/framework/scripts/tts-providers/index.js +158 -0
- package/framework/scripts/tts-providers/openai-provider.js +143 -0
- package/framework/version.json +63 -0
- package/lib/authoring-api.js +919 -0
- package/lib/build-linter.js +450 -0
- package/lib/build-packaging.js +186 -0
- package/lib/build.js +88 -0
- package/lib/cloud.js +691 -0
- package/lib/convert.js +341 -0
- package/lib/course-parser.js +936 -0
- package/lib/course-writer.js +258 -0
- package/lib/create.js +248 -0
- package/lib/css-index.js +237 -0
- package/lib/dev.js +51 -0
- package/lib/export-content.js +1246 -0
- package/lib/headless-browser.js +413 -0
- package/lib/import.js +377 -0
- package/lib/index.js +80 -0
- package/lib/info.js +79 -0
- package/lib/interaction-formatters.js +568 -0
- package/lib/manifest/cmi5-manifest.js +63 -0
- package/lib/manifest/lti-tool-config.js +53 -0
- package/lib/manifest/manifest-factory.js +99 -0
- package/lib/manifest/scorm-12-manifest.js +61 -0
- package/lib/manifest/scorm-2004-manifest.js +94 -0
- package/lib/manifest/scorm-proxy-manifest.js +104 -0
- package/lib/manifest-parser.js +96 -0
- package/lib/mcp-prompts.js +753 -0
- package/lib/mcp-server.js +316 -0
- package/lib/narration.js +53 -0
- package/lib/pdf-structure.js +142 -0
- package/lib/preview-export.js +231 -0
- package/lib/preview-routes-api.js +662 -0
- package/lib/preview-routes-editing.js +159 -0
- package/lib/preview-routes-lms.js +230 -0
- package/lib/preview-server.js +564 -0
- package/lib/project-utils.js +269 -0
- package/lib/proxy-templates/proxy.html +68 -0
- package/lib/proxy-templates/scorm-bridge.js +112 -0
- package/lib/scaffold.js +193 -0
- package/lib/schema-extractor.js +361 -0
- package/lib/slide-source-editor.js +586 -0
- package/lib/stub-player/app-viewer.js +195 -0
- package/lib/stub-player/app.js +370 -0
- package/lib/stub-player/catalog-panel.js +312 -0
- package/lib/stub-player/config-panel.js +1303 -0
- package/lib/stub-player/content-generator.js +586 -0
- package/lib/stub-player/content-viewer.js +173 -0
- package/lib/stub-player/debug-panel.js +420 -0
- package/lib/stub-player/edit-mode.js +922 -0
- package/lib/stub-player/edit-utils.js +400 -0
- package/lib/stub-player/header-bar.js +354 -0
- package/lib/stub-player/interaction-editor.js +210 -0
- package/lib/stub-player/interactions-panel.js +565 -0
- package/lib/stub-player/lms-api.js +1094 -0
- package/lib/stub-player/login-screen.js +74 -0
- package/lib/stub-player/outline-mode.js +689 -0
- package/lib/stub-player/styles/_assessments-panel.css +245 -0
- package/lib/stub-player/styles/_base.css +89 -0
- package/lib/stub-player/styles/_catalog-icons.css +96 -0
- package/lib/stub-player/styles/_catalog-panel.css +291 -0
- package/lib/stub-player/styles/_config-panel.css +636 -0
- package/lib/stub-player/styles/_content-viewer.css +834 -0
- package/lib/stub-player/styles/_debug-panel.css +576 -0
- package/lib/stub-player/styles/_edit-mode.css +128 -0
- package/lib/stub-player/styles/_header-bar.css +343 -0
- package/lib/stub-player/styles/_interaction-editor.css +140 -0
- package/lib/stub-player/styles/_interactions-panel.css +1038 -0
- package/lib/stub-player/styles/_login-screen.css +102 -0
- package/lib/stub-player/styles/_outline-mode.css +752 -0
- package/lib/stub-player/styles.css +15 -0
- package/lib/stub-player.js +160 -0
- package/lib/test-data-reporting.js +176 -0
- package/lib/test-error-reporting.js +146 -0
- package/lib/token.js +86 -0
- package/lib/upgrade.js +257 -0
- package/lib/validation-rules.js +517 -0
- package/lib/vite-plugin-content-discovery.js +296 -0
- package/package.json +108 -0
- package/schemas/XMLSchema.dtd +402 -0
- package/schemas/adlcp_v1p3.xsd +111 -0
- package/schemas/adlnav_v1p3.xsd +61 -0
- package/schemas/adlseq_v1p3.xsd +93 -0
- package/schemas/common/anyElement.xsd +27 -0
- package/schemas/common/dataTypes.xsd +138 -0
- package/schemas/common/elementNames.xsd +767 -0
- package/schemas/common/elementTypes.xsd +786 -0
- package/schemas/common/rootElement.xsd +31 -0
- package/schemas/common/vocabTypes.xsd +345 -0
- package/schemas/common/vocabValues.xsd +257 -0
- package/schemas/datatypes.dtd +203 -0
- package/schemas/ims_xml.xsd +35 -0
- package/schemas/imscp_v1p1.xsd +368 -0
- package/schemas/imsss_v1p0.xsd +67 -0
- package/schemas/imsss_v1p0auxresource.xsd +19 -0
- package/schemas/imsss_v1p0control.xsd +20 -0
- package/schemas/imsss_v1p0delivery.xsd +17 -0
- package/schemas/imsss_v1p0limit.xsd +47 -0
- package/schemas/imsss_v1p0objective.xsd +67 -0
- package/schemas/imsss_v1p0random.xsd +16 -0
- package/schemas/imsss_v1p0rollup.xsd +46 -0
- package/schemas/imsss_v1p0seqrule.xsd +108 -0
- package/schemas/imsss_v1p0util.xsd +94 -0
- package/schemas/license.txt +17 -0
- package/schemas/lom.xsd +102 -0
- package/schemas/lomCustom.xsd +62 -0
- package/schemas/lomLoose.xsd +62 -0
- package/schemas/lomStrict.xsd +62 -0
- package/schemas/xml.xsd +81 -0
- package/template/.env.example +92 -0
- package/template/course/assets/audio/example-intro.mp3 +0 -0
- package/template/course/assets/audio/example-ui-demo--compact-player.mp3 +0 -0
- package/template/course/assets/audio/example-ui-demo--demo-modal.mp3 +0 -0
- package/template/course/assets/audio/example-ui-demo--full-player.mp3 +0 -0
- package/template/course/assets/docs/example_md_1.md +39 -0
- package/template/course/assets/docs/example_md_2.md +41 -0
- package/template/course/assets/docs/example_pdf_1_thumbnail.png +0 -0
- package/template/course/assets/docs/example_pdf_2.pdf +0 -0
- package/template/course/assets/images/course-architecture.svg +36 -0
- package/template/course/assets/images/logo.svg +14 -0
- package/template/course/assets/widgets/counter-demo.html +190 -0
- package/template/course/assets/widgets/gravity-painter.html +384 -0
- package/template/course/course-config.js +539 -0
- package/template/course/icons.js +19 -0
- package/template/course/interactions/PLUGIN_GUIDE.md +97 -0
- package/template/course/slides/example-course-structure.js +138 -0
- package/template/course/slides/example-final-exam.js +144 -0
- package/template/course/slides/example-finishing.js +127 -0
- package/template/course/slides/example-interactions-showcase.js +615 -0
- package/template/course/slides/example-preview-tour.js +129 -0
- package/template/course/slides/example-remedial.js +143 -0
- package/template/course/slides/example-summary.js +103 -0
- package/template/course/slides/example-ui-showcase.js +1805 -0
- package/template/course/slides/example-welcome.js +123 -0
- package/template/course/slides/example-workflow.js +140 -0
- package/template/course/theme.css +165 -0
- package/template/eslint.config.js +47 -0
- package/template/package.json +28 -0
- package/template/vite.config.js +339 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
CARDS - Card component styles with variants and modifiers
|
|
3
|
+
============================================================================
|
|
4
|
+
|
|
5
|
+
WHAT: Reusable card components for grouping and organizing content
|
|
6
|
+
|
|
7
|
+
INCLUDES:
|
|
8
|
+
- Base card styles (.card, .feature-card, .concept-card, .stat-card)
|
|
9
|
+
- Optional hover effects with .interactive modifier
|
|
10
|
+
|
|
11
|
+
DEPENDENCIES:
|
|
12
|
+
- design-tokens.css (--color-*, --space-*, --shadow-*, --transition-*)
|
|
13
|
+
|
|
14
|
+
USED BY:
|
|
15
|
+
- Content slides (grouping related information)
|
|
16
|
+
- Feature showcases
|
|
17
|
+
- Statistics displays
|
|
18
|
+
- Concept explanations
|
|
19
|
+
- UI components (intro-cards, steps, features, etc.)
|
|
20
|
+
|
|
21
|
+
AI DEBUGGING TIPS:
|
|
22
|
+
- Hover effect not working? Add .interactive class to enable hover
|
|
23
|
+
- Shimmer not animating? Verify @keyframes shimmer and prefers-reduced-motion
|
|
24
|
+
- Card not visible? Check z-index and overflow:hidden on parent
|
|
25
|
+
- Shadow not showing? Ensure parent doesn't have overflow:hidden
|
|
26
|
+
|
|
27
|
+
STRUCTURE:
|
|
28
|
+
1. Base card styles (static by default)
|
|
29
|
+
2. Interactive modifier (opt-in hover effects)
|
|
30
|
+
3. Card body/footer patterns
|
|
31
|
+
|
|
32
|
+
COMMON CLASSES:
|
|
33
|
+
.card - Base card (static, most common)
|
|
34
|
+
.feature-card - For feature highlights
|
|
35
|
+
.concept-card - For explanatory concepts
|
|
36
|
+
.stat-card - For statistics/metrics
|
|
37
|
+
.interactive - Enable hover effects for clickable cards
|
|
38
|
+
|
|
39
|
+
LAST UPDATED: 2024-12-04
|
|
40
|
+
============================================================================ */
|
|
41
|
+
|
|
42
|
+
/* Card Component - Unified base class for all card types
|
|
43
|
+
Cards are static content containers by default (no hover effects).
|
|
44
|
+
This follows UX best practice: hover effects should only appear on
|
|
45
|
+
interactive elements to avoid misleading users about clickability.
|
|
46
|
+
*/
|
|
47
|
+
.card,
|
|
48
|
+
.feature-card,
|
|
49
|
+
.concept-card,
|
|
50
|
+
.stat-card {
|
|
51
|
+
background: var(--bg-surface);
|
|
52
|
+
border: var(--border-width-thin) solid var(--border-default);
|
|
53
|
+
border-radius: var(--radius-xl);
|
|
54
|
+
padding: var(--space-6);
|
|
55
|
+
box-shadow: var(--shadow-xs);
|
|
56
|
+
position: relative;
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
/* Flex column layout for easy content distribution */
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Interactive Card Modifier - Opt-in hover effects for clickable cards
|
|
64
|
+
Use .card.interactive when the entire card is clickable/interactive.
|
|
65
|
+
|
|
66
|
+
UX Rationale:
|
|
67
|
+
- Hover effects signal interactivity to users
|
|
68
|
+
- Only apply to cards that perform an action when clicked
|
|
69
|
+
- Includes lift effect, shadow change, border highlight, and shimmer
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
/* Dark mode: elevate cards above surface containers (tabs, page sections) */
|
|
73
|
+
[data-theme="dark"] .card,
|
|
74
|
+
[data-theme="dark"] .feature-card,
|
|
75
|
+
[data-theme="dark"] .concept-card,
|
|
76
|
+
[data-theme="dark"] .stat-card {
|
|
77
|
+
background: var(--bg-elevated);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.card.interactive,
|
|
81
|
+
.feature-card.interactive,
|
|
82
|
+
.concept-card.interactive,
|
|
83
|
+
.stat-card.interactive {
|
|
84
|
+
transition: border-color var(--transition-fast), box-shadow var(--transition-interactive), transform var(--transition-interactive);
|
|
85
|
+
overflow: hidden;
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Interactive card shimmer effect on hover */
|
|
90
|
+
.card.interactive::before,
|
|
91
|
+
.feature-card.interactive::before,
|
|
92
|
+
.concept-card.interactive::before,
|
|
93
|
+
.stat-card.interactive::before {
|
|
94
|
+
content: '';
|
|
95
|
+
position: absolute;
|
|
96
|
+
top: 0;
|
|
97
|
+
left: -100%;
|
|
98
|
+
width: 100%;
|
|
99
|
+
height: 100%;
|
|
100
|
+
background: linear-gradient(90deg, transparent, var(--color-secondary-alpha-05), transparent);
|
|
101
|
+
transition: left var(--transition-slow);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Interactive card hover state */
|
|
105
|
+
.card.interactive:hover,
|
|
106
|
+
.feature-card.interactive:hover,
|
|
107
|
+
.concept-card.interactive:hover,
|
|
108
|
+
.stat-card.interactive:hover {
|
|
109
|
+
box-shadow: var(--shadow-md);
|
|
110
|
+
border-color: color-mix(in srgb, var(--color-primary) 24%, var(--bg-surface));
|
|
111
|
+
transform: translateY(var(--motion-lift-sm));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* No-hover modifier - Explicitly removes any cursor/hover effects
|
|
115
|
+
Use when a card might inherit interactive styles but should be static.
|
|
116
|
+
*/
|
|
117
|
+
.card.no-hover,
|
|
118
|
+
.feature-card.no-hover,
|
|
119
|
+
.concept-card.no-hover,
|
|
120
|
+
.stat-card.no-hover {
|
|
121
|
+
cursor: default;
|
|
122
|
+
pointer-events: auto;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.card.no-hover:hover,
|
|
126
|
+
.feature-card.no-hover:hover,
|
|
127
|
+
.concept-card.no-hover:hover,
|
|
128
|
+
.stat-card.no-hover:hover {
|
|
129
|
+
transform: none;
|
|
130
|
+
box-shadow: var(--shadow-xs);
|
|
131
|
+
border-color: var(--border-default);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.card.interactive:hover::before,
|
|
135
|
+
.feature-card.interactive:hover::before,
|
|
136
|
+
.concept-card.interactive:hover::before,
|
|
137
|
+
.stat-card.interactive:hover::before {
|
|
138
|
+
left: 100%;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Card Header - Top section with background.
|
|
142
|
+
Negative side margins extend into card padding for full-width background.
|
|
143
|
+
Card edge padding is removed via :has() so the header sits flush at top.
|
|
144
|
+
Has a default subtle background — override with any bg-* class. */
|
|
145
|
+
.card-header {
|
|
146
|
+
margin: 0 calc(-1 * var(--space-6)) var(--space-4);
|
|
147
|
+
padding: var(--space-4) var(--space-6);
|
|
148
|
+
border-bottom: var(--border-width-thin) solid var(--border-subtle);
|
|
149
|
+
border-top-left-radius: var(--radius-xl);
|
|
150
|
+
border-top-right-radius: var(--radius-xl);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Default background when no bg-* override is applied */
|
|
154
|
+
.card-header:not([class*="bg-"]) {
|
|
155
|
+
background: var(--bg-subtle);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Dark mode: bg-subtle is darker than the card bg-elevated, inverting
|
|
159
|
+
the visual hierarchy. Use surface-hover so the header stays a step
|
|
160
|
+
above the card body instead of sinking below it. */
|
|
161
|
+
[data-theme="dark"] .card-header:not([class*="bg-"]) {
|
|
162
|
+
background: var(--bg-surface-hover);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* Auto-reset heading/paragraph margins and bold headings inside card-header */
|
|
166
|
+
.card-header > h1,
|
|
167
|
+
.card-header > h2,
|
|
168
|
+
.card-header > h3,
|
|
169
|
+
.card-header > h4,
|
|
170
|
+
.card-header > h5,
|
|
171
|
+
.card-header > h6 {
|
|
172
|
+
margin: 0;
|
|
173
|
+
font-weight: 700;
|
|
174
|
+
line-height: var(--line-height-snug);
|
|
175
|
+
letter-spacing: -0.015em;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.card-header > p {
|
|
179
|
+
margin: 0;
|
|
180
|
+
margin-top: var(--space-1);
|
|
181
|
+
color: var(--text-muted);
|
|
182
|
+
font-size: var(--font-size-sm);
|
|
183
|
+
line-height: var(--line-height-normal);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.card-header.no-border {
|
|
187
|
+
border-bottom: none;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Card Body - Expands to fill available space */
|
|
191
|
+
.card-body {
|
|
192
|
+
flex: 1 1 auto;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.card-body > p {
|
|
196
|
+
color: var(--text-body);
|
|
197
|
+
line-height: var(--line-height-relaxed);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Card Footer - Bottom section for actions.
|
|
201
|
+
margin-top: auto pushes footer to bottom in flex cards.
|
|
202
|
+
Negative side margins extend to card edges like the header. */
|
|
203
|
+
.card-footer {
|
|
204
|
+
margin: auto calc(-1 * var(--space-6)) 0;
|
|
205
|
+
padding: var(--space-4) var(--space-6);
|
|
206
|
+
border-top: var(--border-width-thin) solid var(--border-subtle);
|
|
207
|
+
border-bottom-left-radius: var(--radius-xl);
|
|
208
|
+
border-bottom-right-radius: var(--radius-xl);
|
|
209
|
+
font-size: var(--font-size-sm);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.card-footer:empty {
|
|
213
|
+
display: none;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.card-footer.no-border {
|
|
217
|
+
border-top: none;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* Edge padding reset — zero card padding where header/footer sit at edges.
|
|
221
|
+
This makes the header/footer background extend flush to the card border. */
|
|
222
|
+
.card:has(> .card-header:first-child) {
|
|
223
|
+
padding-top: 0;
|
|
224
|
+
}
|
|
225
|
+
.card:has(> .card-footer:last-child) {
|
|
226
|
+
padding-bottom: 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
/* ============================================================================
|
|
231
|
+
CARD STYLE VARIANTS
|
|
232
|
+
============================================================================
|
|
233
|
+
|
|
234
|
+
Use these modifier classes to change the visual appearance of cards.
|
|
235
|
+
Combine with .interactive if the card should have hover effects.
|
|
236
|
+
|
|
237
|
+
USAGE:
|
|
238
|
+
<div class="card card-outlined">...</div>
|
|
239
|
+
<div class="card card-elevated interactive">...</div>
|
|
240
|
+
|
|
241
|
+
============================================================================ */
|
|
242
|
+
|
|
243
|
+
/* Outlined - Border only, no background fill */
|
|
244
|
+
.card-outlined,
|
|
245
|
+
.card.card-outlined,
|
|
246
|
+
.feature-card.card-outlined,
|
|
247
|
+
.concept-card.card-outlined,
|
|
248
|
+
.stat-card.card-outlined {
|
|
249
|
+
background: transparent;
|
|
250
|
+
border: var(--border-width-sm) solid var(--border-strong);
|
|
251
|
+
box-shadow: none;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.card-outlined.interactive:hover {
|
|
255
|
+
background: var(--bg-subtle);
|
|
256
|
+
border-color: var(--color-primary);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Elevated - Stronger shadow, more depth */
|
|
260
|
+
.card-elevated,
|
|
261
|
+
.card.card-elevated,
|
|
262
|
+
.feature-card.card-elevated,
|
|
263
|
+
.concept-card.card-elevated,
|
|
264
|
+
.stat-card.card-elevated {
|
|
265
|
+
box-shadow: var(--shadow-lg);
|
|
266
|
+
border-color: transparent;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.card-elevated.interactive:hover {
|
|
270
|
+
box-shadow: var(--shadow-xl, 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04));
|
|
271
|
+
transform: translateY(-6px);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Flat - No shadow, minimal border */
|
|
275
|
+
.card-flat,
|
|
276
|
+
.card.card-flat,
|
|
277
|
+
.feature-card.card-flat,
|
|
278
|
+
.concept-card.card-flat,
|
|
279
|
+
.stat-card.card-flat {
|
|
280
|
+
box-shadow: none;
|
|
281
|
+
border: var(--border-width-thin) solid var(--border-default);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.card-flat.interactive:hover {
|
|
285
|
+
box-shadow: var(--shadow-xs);
|
|
286
|
+
border-color: var(--border-strong);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* Gradient Border - Decorative gradient border effect */
|
|
290
|
+
.card-gradient,
|
|
291
|
+
.card.card-gradient,
|
|
292
|
+
.feature-card.card-gradient,
|
|
293
|
+
.concept-card.card-gradient,
|
|
294
|
+
.stat-card.card-gradient {
|
|
295
|
+
border: none;
|
|
296
|
+
background: var(--bg-surface);
|
|
297
|
+
position: relative;
|
|
298
|
+
z-index: 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.card-gradient::before {
|
|
302
|
+
content: '';
|
|
303
|
+
position: absolute;
|
|
304
|
+
inset: 0;
|
|
305
|
+
padding: 2px;
|
|
306
|
+
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-secondary) 50%, var(--color-accent) 100%);
|
|
307
|
+
border-radius: inherit;
|
|
308
|
+
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
309
|
+
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
|
310
|
+
-webkit-mask-composite: xor;
|
|
311
|
+
mask-composite: exclude;
|
|
312
|
+
z-index: -1;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* Accent Top - Colored top border accent */
|
|
316
|
+
.card-accent-top,
|
|
317
|
+
.card.card-accent-top,
|
|
318
|
+
.feature-card.card-accent-top,
|
|
319
|
+
.concept-card.card-accent-top,
|
|
320
|
+
.stat-card.card-accent-top {
|
|
321
|
+
border-top: 4px solid var(--color-primary);
|
|
322
|
+
border-top-left-radius: var(--radius-md);
|
|
323
|
+
border-top-right-radius: var(--radius-md);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* Allow customization of accent color */
|
|
327
|
+
.card-accent-top[data-accent="secondary"] {
|
|
328
|
+
border-top-color: var(--color-secondary);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.card-accent-top[data-accent="accent"] {
|
|
332
|
+
border-top-color: var(--color-accent);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.card-accent-top[data-accent="success"] {
|
|
336
|
+
border-top-color: var(--color-success);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.card-accent-top[data-accent="warning"] {
|
|
340
|
+
border-top-color: var(--color-warning);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.card-accent-top[data-accent="error"] {
|
|
344
|
+
border-top-color: var(--color-danger);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.card-accent-top[data-accent="info"] {
|
|
348
|
+
border-top-color: var(--color-info);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/* Accent Left - Colored left border accent */
|
|
352
|
+
.card-accent-left,
|
|
353
|
+
.card.card-accent-left,
|
|
354
|
+
.feature-card.card-accent-left,
|
|
355
|
+
.concept-card.card-accent-left,
|
|
356
|
+
.stat-card.card-accent-left {
|
|
357
|
+
border-left: 4px solid var(--color-primary);
|
|
358
|
+
border-top-left-radius: var(--radius-md);
|
|
359
|
+
border-bottom-left-radius: var(--radius-md);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* Allow customization of accent color */
|
|
363
|
+
.card-accent-left[data-accent="secondary"] {
|
|
364
|
+
border-left-color: var(--color-secondary);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.card-accent-left[data-accent="accent"] {
|
|
368
|
+
border-left-color: var(--color-accent);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.card-accent-left[data-accent="success"] {
|
|
372
|
+
border-left-color: var(--color-success);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.card-accent-left[data-accent="warning"] {
|
|
376
|
+
border-left-color: var(--color-warning);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.card-accent-left[data-accent="error"] {
|
|
380
|
+
border-left-color: var(--color-danger);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.card-accent-left[data-accent="info"] {
|
|
384
|
+
border-left-color: var(--color-info);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
/* ============================================================================
|
|
389
|
+
CARD GRID LAYOUTS
|
|
390
|
+
============================================================================
|
|
391
|
+
|
|
392
|
+
Grid layouts that ensure cards are equal height and properly aligned.
|
|
393
|
+
Use these instead of generic grid classes when displaying cards side-by-side.
|
|
394
|
+
|
|
395
|
+
USAGE:
|
|
396
|
+
<div class="card-grid"> <!-- Auto-fit responsive grid -->
|
|
397
|
+
<div class="card-grid-2"> <!-- Always 2 columns -->
|
|
398
|
+
<div class="card-grid-3"> <!-- Always 3 columns -->
|
|
399
|
+
|
|
400
|
+
The cards inside will automatically stretch to equal heights.
|
|
401
|
+
|
|
402
|
+
============================================================================ */
|
|
403
|
+
|
|
404
|
+
/* Base card grid - responsive auto-fit */
|
|
405
|
+
.card-grid {
|
|
406
|
+
display: grid;
|
|
407
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
408
|
+
gap: var(--space-4);
|
|
409
|
+
align-items: stretch;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/* Ensure cards stretch to fill grid cell height */
|
|
413
|
+
.card-grid > .card,
|
|
414
|
+
.card-grid > .feature-card,
|
|
415
|
+
.card-grid > .concept-card,
|
|
416
|
+
.card-grid > .stat-card,
|
|
417
|
+
.card-grid-2 > .card,
|
|
418
|
+
.card-grid-2 > .feature-card,
|
|
419
|
+
.card-grid-2 > .concept-card,
|
|
420
|
+
.card-grid-2 > .stat-card,
|
|
421
|
+
.card-grid-3 > .card,
|
|
422
|
+
.card-grid-3 > .feature-card,
|
|
423
|
+
.card-grid-3 > .concept-card,
|
|
424
|
+
.card-grid-3 > .stat-card {
|
|
425
|
+
height: 100%;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/* Note: .flip-card grid support is in flip-cards.css (min-width required
|
|
429
|
+
because flip card content is absolutely positioned with no intrinsic size) */
|
|
430
|
+
|
|
431
|
+
/* Fixed 2-column grid */
|
|
432
|
+
.card-grid-2 {
|
|
433
|
+
display: grid;
|
|
434
|
+
grid-template-columns: repeat(2, 1fr);
|
|
435
|
+
grid-auto-rows: 1fr; /* Equal height rows across entire grid */
|
|
436
|
+
gap: var(--space-4);
|
|
437
|
+
align-items: stretch;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* Fixed 3-column grid */
|
|
441
|
+
.card-grid-3 {
|
|
442
|
+
display: grid;
|
|
443
|
+
grid-template-columns: repeat(3, 1fr);
|
|
444
|
+
grid-auto-rows: 1fr; /* Equal height rows across entire grid */
|
|
445
|
+
gap: var(--space-4);
|
|
446
|
+
align-items: stretch;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/* Larger gap variants */
|
|
450
|
+
.card-grid.gap-6,
|
|
451
|
+
.card-grid-2.gap-6,
|
|
452
|
+
.card-grid-3.gap-6 {
|
|
453
|
+
gap: var(--space-6);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.card-grid.gap-8,
|
|
457
|
+
.card-grid-2.gap-8,
|
|
458
|
+
.card-grid-3.gap-8 {
|
|
459
|
+
gap: var(--space-8);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/* Responsive: Stack on mobile */
|
|
463
|
+
@media (max-width: 768px) {
|
|
464
|
+
.card-grid-2,
|
|
465
|
+
.card-grid-3 {
|
|
466
|
+
grid-template-columns: 1fr;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* Tablet: 2 columns for 3-col grid */
|
|
471
|
+
@media (min-width: 769px) and (max-width: 1024px) {
|
|
472
|
+
.card-grid-3 {
|
|
473
|
+
grid-template-columns: repeat(2, 1fr);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
CAROUSEL - Image carousel/slideshow component
|
|
3
|
+
============================================================================
|
|
4
|
+
|
|
5
|
+
PURPOSE: Responsive image carousel with navigation and indicators
|
|
6
|
+
|
|
7
|
+
INCLUDES:
|
|
8
|
+
- Carousel container and track
|
|
9
|
+
- Slide layout
|
|
10
|
+
- Navigation buttons (prev/next)
|
|
11
|
+
- Dot indicators
|
|
12
|
+
- Responsive behavior
|
|
13
|
+
|
|
14
|
+
DEPENDENCIES:
|
|
15
|
+
- Requires: design-tokens.css (for CSS variables)
|
|
16
|
+
- Requires: components/buttons.css (for button states)
|
|
17
|
+
|
|
18
|
+
USED BY:
|
|
19
|
+
- Image galleries
|
|
20
|
+
- Content slideshows
|
|
21
|
+
- Photo tours
|
|
22
|
+
|
|
23
|
+
AI DEBUGGING TIPS:
|
|
24
|
+
- Slides not showing? Check carousel-track transform
|
|
25
|
+
- Buttons not clickable? Verify z-index and pointer-events
|
|
26
|
+
- Dots not aligning? Check absolute positioning
|
|
27
|
+
- Images overflowing? Verify flex: 0 0 100% on slides
|
|
28
|
+
|
|
29
|
+
============================================================================ */
|
|
30
|
+
|
|
31
|
+
.carousel {
|
|
32
|
+
position: relative;
|
|
33
|
+
width: 100%;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
border-radius: var(--radius-lg);
|
|
36
|
+
box-shadow: var(--shadow-lg);
|
|
37
|
+
min-height: var(--size-carousel-height); /* Ensure consistent height */
|
|
38
|
+
background: var(--bg-muted);
|
|
39
|
+
isolation: isolate; /* Create stacking context */
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.carousel-track {
|
|
45
|
+
display: flex;
|
|
46
|
+
transition: transform 0.5s cubic-bezier(0.25, 1, 0.5, 1); /* Smoother easing */
|
|
47
|
+
flex: 1; /* Fill the container height */
|
|
48
|
+
height: 100%;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.carousel-slide {
|
|
52
|
+
flex: 0 0 100%;
|
|
53
|
+
width: 100%;
|
|
54
|
+
height: 100%;
|
|
55
|
+
position: relative;
|
|
56
|
+
display: flex;
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
align-items: center;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
background-color: var(--bg-subtle);
|
|
61
|
+
padding: var(--space-6); /* Ensure content isn't against edges */
|
|
62
|
+
box-sizing: border-box;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.carousel-slide img {
|
|
66
|
+
width: 100%;
|
|
67
|
+
height: 100%;
|
|
68
|
+
object-fit: cover;
|
|
69
|
+
display: block;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Navigation Buttons */
|
|
73
|
+
.carousel-button {
|
|
74
|
+
position: absolute;
|
|
75
|
+
top: 50%;
|
|
76
|
+
transform: translateY(-50%);
|
|
77
|
+
width: var(--carousel-control-size);
|
|
78
|
+
height: var(--carousel-control-size);
|
|
79
|
+
border-radius: 50%;
|
|
80
|
+
background-color: var(--carousel-control-bg);
|
|
81
|
+
color: var(--carousel-control-text);
|
|
82
|
+
border: var(--border-width-thin) solid var(--carousel-control-border);
|
|
83
|
+
box-shadow: var(--shadow-md);
|
|
84
|
+
font-size: 1.5rem;
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
z-index: 10;
|
|
90
|
+
transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease, opacity 0.2s ease;
|
|
91
|
+
opacity: 0; /* Hidden by default for cleaner look */
|
|
92
|
+
padding: 0;
|
|
93
|
+
line-height: 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Show buttons on hover or focus */
|
|
97
|
+
.carousel:hover .carousel-button,
|
|
98
|
+
.carousel-button:focus-visible {
|
|
99
|
+
opacity: 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.carousel-button:hover:not(:disabled) {
|
|
103
|
+
background-color: var(--carousel-control-bg-hover);
|
|
104
|
+
transform: translateY(-50%) scale(1.1);
|
|
105
|
+
box-shadow: var(--shadow-lg);
|
|
106
|
+
color: var(--carousel-control-text-hover);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.carousel-button:focus-visible {
|
|
110
|
+
outline: 2px solid var(--carousel-control-focus);
|
|
111
|
+
outline-offset: 2px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.carousel-button:disabled {
|
|
115
|
+
opacity: 0;
|
|
116
|
+
cursor: default;
|
|
117
|
+
pointer-events: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.carousel-button.prev {
|
|
121
|
+
left: var(--carousel-control-offset);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.carousel-button.next {
|
|
125
|
+
right: var(--carousel-control-offset);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Dots Indicators */
|
|
129
|
+
.carousel-dots {
|
|
130
|
+
position: absolute;
|
|
131
|
+
bottom: var(--carousel-dots-bottom);
|
|
132
|
+
left: 50%;
|
|
133
|
+
transform: translateX(-50%);
|
|
134
|
+
display: flex;
|
|
135
|
+
gap: var(--carousel-dots-gap);
|
|
136
|
+
z-index: 10;
|
|
137
|
+
padding: var(--carousel-dots-padding-y) var(--carousel-dots-padding-x);
|
|
138
|
+
background-color: var(--carousel-dots-bg);
|
|
139
|
+
backdrop-filter: blur(4px);
|
|
140
|
+
border-radius: var(--radius-full);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.carousel-dot {
|
|
144
|
+
width: var(--carousel-dot-size);
|
|
145
|
+
height: var(--carousel-dot-size);
|
|
146
|
+
border-radius: 50%;
|
|
147
|
+
background-color: var(--carousel-dot-bg);
|
|
148
|
+
border: none;
|
|
149
|
+
cursor: pointer;
|
|
150
|
+
padding: 0;
|
|
151
|
+
transition: background-color 0.3s ease, transform 0.3s ease, width 0.3s ease, border-radius 0.3s ease, opacity 0.3s ease;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.carousel-dot:hover {
|
|
155
|
+
background-color: var(--carousel-dot-bg-hover);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.carousel-dot.active {
|
|
159
|
+
background-color: var(--carousel-dot-bg-active);
|
|
160
|
+
transform: scale(1);
|
|
161
|
+
width: var(--carousel-dot-active-width); /* Pill shape for active state */
|
|
162
|
+
border-radius: var(--radius-full);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.carousel-dot:focus-visible {
|
|
166
|
+
outline: 2px solid var(--carousel-dot-focus);
|
|
167
|
+
outline-offset: 2px;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* Optional Caption Support */
|
|
171
|
+
.carousel-caption {
|
|
172
|
+
position: absolute;
|
|
173
|
+
bottom: 0;
|
|
174
|
+
left: 0;
|
|
175
|
+
right: 0;
|
|
176
|
+
padding: var(--carousel-caption-padding-top) var(--carousel-caption-padding-x) var(--carousel-caption-padding-bottom); /* Extra top padding for dots */
|
|
177
|
+
background: var(--carousel-caption-overlay);
|
|
178
|
+
color: var(--color-white);
|
|
179
|
+
text-align: center;
|
|
180
|
+
pointer-events: none;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.carousel-caption h3 {
|
|
184
|
+
color: var(--color-white);
|
|
185
|
+
margin-bottom: 0.5rem;
|
|
186
|
+
font-size: var(--font-size-lg);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.carousel-caption p {
|
|
190
|
+
color: var(--color-white-alpha-95);
|
|
191
|
+
margin: 0;
|
|
192
|
+
font-size: var(--font-size-sm);
|
|
193
|
+
}
|