@echelon-foundry/design-system 0.2.0-main.15.1

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 (148) hide show
  1. package/README.md +82 -0
  2. package/dist/all.css +3461 -0
  3. package/dist/assessment.css +1123 -0
  4. package/dist/brands/echelon.css +91 -0
  5. package/dist/brands/example-harbor.css +91 -0
  6. package/dist/brands/index.json +17 -0
  7. package/dist/build-metrics.json +152 -0
  8. package/dist/components.css +2123 -0
  9. package/dist/foundations.css +113 -0
  10. package/dist/patterns/alert.html +8 -0
  11. package/dist/patterns/allocation.html +24 -0
  12. package/dist/patterns/best-worst.html +21 -0
  13. package/dist/patterns/binary-choice.html +15 -0
  14. package/dist/patterns/checkbox.html +13 -0
  15. package/dist/patterns/choice-group.html +27 -0
  16. package/dist/patterns/collection-toolbar.html +22 -0
  17. package/dist/patterns/combobox.html +13 -0
  18. package/dist/patterns/command-palette.html +14 -0
  19. package/dist/patterns/composer.html +19 -0
  20. package/dist/patterns/conflict-review.html +17 -0
  21. package/dist/patterns/conversation.html +23 -0
  22. package/dist/patterns/dashboard-grid.html +5 -0
  23. package/dist/patterns/data-grid.html +30 -0
  24. package/dist/patterns/date-range.html +13 -0
  25. package/dist/patterns/dialog.html +15 -0
  26. package/dist/patterns/diff-viewer.html +22 -0
  27. package/dist/patterns/disclosure.html +6 -0
  28. package/dist/patterns/empty-state.html +6 -0
  29. package/dist/patterns/file-upload.html +19 -0
  30. package/dist/patterns/flyout.html +72 -0
  31. package/dist/patterns/hierarchical-choice.html +25 -0
  32. package/dist/patterns/hierarchical-multi-choice.html +27 -0
  33. package/dist/patterns/image-choice.html +25 -0
  34. package/dist/patterns/master-detail.html +16 -0
  35. package/dist/patterns/matrix-single.html +26 -0
  36. package/dist/patterns/menu.html +8 -0
  37. package/dist/patterns/metric-card.html +6 -0
  38. package/dist/patterns/mobile-action-bar.html +4 -0
  39. package/dist/patterns/multi-choice.html +23 -0
  40. package/dist/patterns/numeric-stepper.html +5 -0
  41. package/dist/patterns/obligation-panel.html +36 -0
  42. package/dist/patterns/operation-status.html +12 -0
  43. package/dist/patterns/ordinal-scale.html +42 -0
  44. package/dist/patterns/pagination.html +12 -0
  45. package/dist/patterns/pairwise-choice.html +21 -0
  46. package/dist/patterns/popover.html +6 -0
  47. package/dist/patterns/preview-surface.html +14 -0
  48. package/dist/patterns/provenance-trail.html +9 -0
  49. package/dist/patterns/question.html +13 -0
  50. package/dist/patterns/range-entry.html +18 -0
  51. package/dist/patterns/ranking.html +32 -0
  52. package/dist/patterns/readiness-checklist.html +12 -0
  53. package/dist/patterns/record-header.html +17 -0
  54. package/dist/patterns/rule-builder.html +37 -0
  55. package/dist/patterns/search.html +8 -0
  56. package/dist/patterns/segmented-control.html +13 -0
  57. package/dist/patterns/select.html +12 -0
  58. package/dist/patterns/semantic-differential.html +23 -0
  59. package/dist/patterns/skeleton.html +7 -0
  60. package/dist/patterns/slider.html +11 -0
  61. package/dist/patterns/special-choice.html +15 -0
  62. package/dist/patterns/status-lozenge.html +6 -0
  63. package/dist/patterns/survey-progress.html +8 -0
  64. package/dist/patterns/switch.html +14 -0
  65. package/dist/patterns/symbol-rating.html +31 -0
  66. package/dist/patterns/tabs.html +11 -0
  67. package/dist/patterns/timeline.html +19 -0
  68. package/dist/patterns/toast.html +10 -0
  69. package/dist/patterns/understanding.html +32 -0
  70. package/dist/patterns/validation-message.html +4 -0
  71. package/dist/patterns/validation-summary.html +10 -0
  72. package/dist/patterns/wizard.html +19 -0
  73. package/dist/patterns/work-queue.html +20 -0
  74. package/dist/skins.css +29 -0
  75. package/dist/tokens.css +99 -0
  76. package/docs/BRANDING.md +148 -0
  77. package/package.json +60 -0
  78. package/patterns/alert.html +8 -0
  79. package/patterns/allocation.html +24 -0
  80. package/patterns/assessment.manifest.md +93 -0
  81. package/patterns/best-worst.html +21 -0
  82. package/patterns/binary-choice.html +15 -0
  83. package/patterns/checkbox.html +13 -0
  84. package/patterns/choice-group.html +27 -0
  85. package/patterns/collection-toolbar.html +22 -0
  86. package/patterns/combobox.html +13 -0
  87. package/patterns/command-palette.html +14 -0
  88. package/patterns/composer.html +19 -0
  89. package/patterns/composer.manifest.md +27 -0
  90. package/patterns/conflict-review.html +17 -0
  91. package/patterns/conversation.html +23 -0
  92. package/patterns/conversation.manifest.md +21 -0
  93. package/patterns/dashboard-grid.html +5 -0
  94. package/patterns/data-grid.html +30 -0
  95. package/patterns/date-range.html +13 -0
  96. package/patterns/dialog.html +15 -0
  97. package/patterns/diff-viewer.html +22 -0
  98. package/patterns/disclosure.html +6 -0
  99. package/patterns/empty-state.html +6 -0
  100. package/patterns/file-upload.html +19 -0
  101. package/patterns/flyout.html +72 -0
  102. package/patterns/flyout.manifest.md +43 -0
  103. package/patterns/hierarchical-choice.html +25 -0
  104. package/patterns/hierarchical-multi-choice.html +27 -0
  105. package/patterns/image-choice.html +25 -0
  106. package/patterns/manifest.md +46 -0
  107. package/patterns/master-detail.html +16 -0
  108. package/patterns/matrix-single.html +26 -0
  109. package/patterns/menu.html +8 -0
  110. package/patterns/metric-card.html +6 -0
  111. package/patterns/mobile-action-bar.html +4 -0
  112. package/patterns/multi-choice.html +23 -0
  113. package/patterns/numeric-stepper.html +5 -0
  114. package/patterns/obligation-panel.html +36 -0
  115. package/patterns/operation-status.html +12 -0
  116. package/patterns/ordinal-scale.html +42 -0
  117. package/patterns/pagination.html +12 -0
  118. package/patterns/pairwise-choice.html +21 -0
  119. package/patterns/popover.html +6 -0
  120. package/patterns/preview-surface.html +14 -0
  121. package/patterns/provenance-trail.html +9 -0
  122. package/patterns/question.html +13 -0
  123. package/patterns/range-entry.html +18 -0
  124. package/patterns/ranking.html +32 -0
  125. package/patterns/readiness-checklist.html +12 -0
  126. package/patterns/record-header.html +17 -0
  127. package/patterns/rule-builder.html +37 -0
  128. package/patterns/search.html +8 -0
  129. package/patterns/segmented-control.html +13 -0
  130. package/patterns/select.html +12 -0
  131. package/patterns/semantic-differential.html +23 -0
  132. package/patterns/skeleton.html +7 -0
  133. package/patterns/slider.html +11 -0
  134. package/patterns/special-choice.html +15 -0
  135. package/patterns/status-lozenge.html +6 -0
  136. package/patterns/survey-progress.html +8 -0
  137. package/patterns/switch.html +14 -0
  138. package/patterns/symbol-rating.html +31 -0
  139. package/patterns/tabs.html +11 -0
  140. package/patterns/timeline.html +19 -0
  141. package/patterns/toast.html +10 -0
  142. package/patterns/understanding.html +32 -0
  143. package/patterns/understanding.manifest.md +26 -0
  144. package/patterns/validation-message.html +4 -0
  145. package/patterns/validation-summary.html +10 -0
  146. package/patterns/wizard.html +19 -0
  147. package/patterns/work-queue.html +20 -0
  148. package/schemas/brand-manifest.schema.json +152 -0
@@ -0,0 +1,10 @@
1
+ <button type="button" popovertarget="save-notification" popovertargetaction="show">Show notification</button>
2
+ <aside class="ef-toast" id="save-notification" popover="manual" role="status" data-ef-motion-weight="standard">
3
+ <div class="ef-toast__header">
4
+ <div>
5
+ <h3 class="ef-toast__title">Changes saved</h3>
6
+ <p>The current draft is stored.</p>
7
+ </div>
8
+ <button type="button" popovertarget="save-notification" popovertargetaction="hide" aria-label="Dismiss notification">Close</button>
9
+ </div>
10
+ </aside>
@@ -0,0 +1,32 @@
1
+ <section class="ef-understanding" aria-labelledby="understanding-title">
2
+ <header class="ef-understanding__header">
3
+ <div>
4
+ <span class="ef-component-kicker">Understanding</span>
5
+ <h2 id="understanding-title">I found 4 things</h2>
6
+ <p>Review what the application understood before any consequential transition.</p>
7
+ </div>
8
+ <span class="ef-status-lozenge" data-state="attention">1 question</span>
9
+ </header>
10
+ <ol class="ef-understanding__items">
11
+ <li class="ef-understanding__item" data-ef-state="accepted">
12
+ <span class="ef-understanding__state">Understood</span>
13
+ <div><strong>Medication change</strong><p>Medication increased to 40 mg.</p></div>
14
+ <button type="button">Source</button>
15
+ </li>
16
+ <li class="ef-understanding__item" data-ef-state="accepted">
17
+ <span class="ef-understanding__state">Understood</span>
18
+ <div><strong>Symptom</strong><p>Ankle swelling returned.</p></div>
19
+ <button type="button">Source</button>
20
+ </li>
21
+ <li class="ef-understanding__item" data-ef-state="unknown">
22
+ <span class="ef-understanding__state">Unknown</span>
23
+ <div><strong>Medication frequency</strong><p>The dose frequency was not supplied.</p></div>
24
+ <button type="button">Answer</button>
25
+ </li>
26
+ <li class="ef-understanding__item" data-ef-state="accepted">
27
+ <span class="ef-understanding__state">Understood</span>
28
+ <div><strong>Visit</strong><p>Dr. Smith visit occurred yesterday.</p></div>
29
+ <button type="button">Source</button>
30
+ </li>
31
+ </ol>
32
+ </section>
@@ -0,0 +1,4 @@
1
+ <p class="ef-validation-message" id="question-example-error">
2
+ <span class="ef-validation-message__mark" aria-hidden="true">!</span>
3
+ Choose one response before continuing.
4
+ </p>
@@ -0,0 +1,10 @@
1
+ <div class="ef-validation-summary" role="alert" tabindex="-1" aria-labelledby="validation-summary-title">
2
+ <div class="ef-validation-summary__icon" aria-hidden="true">!</div>
3
+ <div>
4
+ <h2 class="ef-validation-summary__title" id="validation-summary-title">There are 2 responses to review</h2>
5
+ <ul class="ef-validation-summary__list">
6
+ <li><a href="#question-security">Question 4 requires a response.</a></li>
7
+ <li><a href="#question-allocation">Question 8 must total 10 points.</a></li>
8
+ </ul>
9
+ </div>
10
+ </div>
@@ -0,0 +1,19 @@
1
+ <section class="ef-wizard" aria-labelledby="wizard-title">
2
+ <header class="ef-wizard__header">
3
+ <div><span class="ef-wizard__position">Step 2 of 4</span><h3 id="wizard-title">Review details</h3></div>
4
+ <progress value="2" max="4" aria-label="Workflow progress">2 of 4</progress>
5
+ </header>
6
+ <ol class="ef-wizard__steps" aria-label="Workflow steps">
7
+ <li data-state="complete"><span>1</span>Details</li>
8
+ <li data-state="current" aria-current="step"><span>2</span>Review</li>
9
+ <li><span>3</span>Validate</li>
10
+ <li><span>4</span>Publish</li>
11
+ </ol>
12
+ <div class="ef-wizard__body">
13
+ <p>Confirm the supplied information before continuing.</p>
14
+ </div>
15
+ <footer class="ef-wizard__actions">
16
+ <button type="button">Back</button>
17
+ <button type="button">Continue</button>
18
+ </footer>
19
+ </section>
@@ -0,0 +1,20 @@
1
+ <section class="ef-work-queue" aria-labelledby="work-queue-title">
2
+ <header class="ef-work-queue__header">
3
+ <div><span class="ef-component-kicker">Attention</span><h3 id="work-queue-title">Needs your attention</h3></div>
4
+ <span class="ef-status-lozenge">3 items</span>
5
+ </header>
6
+ <ol class="ef-work-queue__list">
7
+ <li class="ef-work-queue__item">
8
+ <div><strong>Invoice INV-1042 is overdue</strong><p>32 days overdue · Customer follow-up is available.</p></div>
9
+ <button type="button">Review</button>
10
+ </li>
11
+ <li class="ef-work-queue__item">
12
+ <div><strong>Write outcome is unknown</strong><p>Reconcile before retrying or assuming failure.</p></div>
13
+ <button type="button">Reconcile</button>
14
+ </li>
15
+ <li class="ef-work-queue__item">
16
+ <div><strong>Publication validation has warnings</strong><p>2 warnings require review before publishing.</p></div>
17
+ <button type="button">Inspect</button>
18
+ </li>
19
+ </ol>
20
+ </section>
package/dist/skins.css ADDED
@@ -0,0 +1,29 @@
1
+ /* Intentionally unlayered: opt-in skins override layered brand/token presentation primitives. */
2
+ [data-ef-skin="compact"] {
3
+ --ef-primitive-spacing-1: 3px;
4
+ --ef-primitive-spacing-2: 6px;
5
+ --ef-primitive-spacing-3: 9px;
6
+ --ef-primitive-spacing-4: 12px;
7
+ --ef-primitive-spacing-5: 18px;
8
+ --ef-primitive-spacing-6: 24px;
9
+ --ef-primitive-spacing-7: 36px;
10
+ --ef-primitive-spacing-8: 48px;
11
+ --ef-primitive-radius-small: 3px;
12
+ --ef-primitive-radius-medium: 6px;
13
+ }
14
+
15
+ [data-ef-skin="comfortable"] {
16
+ --ef-primitive-spacing-1: 5px;
17
+ --ef-primitive-spacing-2: 10px;
18
+ --ef-primitive-spacing-3: 15px;
19
+ --ef-primitive-spacing-4: 20px;
20
+ --ef-primitive-spacing-5: 30px;
21
+ --ef-primitive-spacing-6: 40px;
22
+ --ef-primitive-spacing-7: 60px;
23
+ --ef-primitive-spacing-8: 80px;
24
+ }
25
+
26
+ [data-ef-skin="square"] {
27
+ --ef-primitive-radius-small: 0;
28
+ --ef-primitive-radius-medium: 0;
29
+ }
@@ -0,0 +1,99 @@
1
+ /* Generated from tokens/echelon.tokens.json. Do not edit directly. */
2
+ @layer echelon.tokens {
3
+ :root {
4
+ --ef-primitive-color-carbon: #171a18;
5
+ --ef-primitive-color-forged-iron: #3a403c;
6
+ --ef-primitive-color-foundry-charcoal: #202421;
7
+ --ef-primitive-color-graphite: #686d68;
8
+ --ef-primitive-color-oxide-bronze: #905831;
9
+ --ef-primitive-color-oxide-bronze-light: #a87e5e;
10
+ --ef-primitive-color-parchment: #f2efe7;
11
+ --ef-primitive-color-stone: #e3e0d7;
12
+ --ef-primitive-color-verdigris: #47756b;
13
+ --ef-primitive-color-verdigris-light: #698d84;
14
+ --ef-primitive-font-family-display: Newsreader, Georgia, serif;
15
+ --ef-primitive-font-family-mono: "IBM Plex Mono", ui-monospace, monospace;
16
+ --ef-primitive-font-family-sans: Manrope, system-ui, sans-serif;
17
+ --ef-primitive-motion-duration-fast: 120ms;
18
+ --ef-primitive-motion-duration-instant: 0ms;
19
+ --ef-primitive-motion-duration-slow: 280ms;
20
+ --ef-primitive-motion-duration-standard: 180ms;
21
+ --ef-primitive-motion-easing-enter: cubic-bezier(0, 0, 0.2, 1);
22
+ --ef-primitive-motion-easing-exit: cubic-bezier(0.4, 0, 1, 1);
23
+ --ef-primitive-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
24
+ --ef-primitive-radius-medium: 8px;
25
+ --ef-primitive-radius-none: 0px;
26
+ --ef-primitive-radius-pill: 999px;
27
+ --ef-primitive-radius-small: 4px;
28
+ --ef-primitive-spacing-1: 4px;
29
+ --ef-primitive-spacing-2: 8px;
30
+ --ef-primitive-spacing-3: 12px;
31
+ --ef-primitive-spacing-4: 16px;
32
+ --ef-primitive-spacing-5: 24px;
33
+ --ef-primitive-spacing-6: 32px;
34
+ --ef-primitive-spacing-7: 48px;
35
+ --ef-primitive-spacing-8: 64px;
36
+ }
37
+ :root, [data-ef-theme="light"] {
38
+ --ef-color-accent-primary: #905831;
39
+ --ef-color-accent-secondary: #47756b;
40
+ --ef-color-border-functional: #3a403c;
41
+ --ef-color-border-subtle: #e3e0d7;
42
+ --ef-color-control-active: #905831;
43
+ --ef-color-control-thumb: #f2efe7;
44
+ --ef-color-control-track: #686d68;
45
+ --ef-color-focus-gap: #f2efe7;
46
+ --ef-color-focus-ring: #171a18;
47
+ --ef-color-surface-inverse: #202421;
48
+ --ef-color-surface-inverse-secondary: #3a403c;
49
+ --ef-color-surface-primary: #f2efe7;
50
+ --ef-color-surface-secondary: #e3e0d7;
51
+ --ef-color-text-heading: #202421;
52
+ --ef-color-text-inverse: #f2efe7;
53
+ --ef-color-text-on-secondary-surface: #3a403c;
54
+ --ef-color-text-primary: #171a18;
55
+ --ef-color-text-secondary: #686d68;
56
+ }
57
+ @media (prefers-color-scheme: dark) {
58
+ :root:not([data-ef-theme]) {
59
+ --ef-color-accent-primary: #a87e5e;
60
+ --ef-color-accent-secondary: #698d84;
61
+ --ef-color-border-functional: #e3e0d7;
62
+ --ef-color-border-subtle: #3a403c;
63
+ --ef-color-control-active: #a87e5e;
64
+ --ef-color-control-thumb: #f2efe7;
65
+ --ef-color-control-track: #686d68;
66
+ --ef-color-focus-gap: #171a18;
67
+ --ef-color-focus-ring: #f2efe7;
68
+ --ef-color-surface-inverse: #f2efe7;
69
+ --ef-color-surface-inverse-secondary: #e3e0d7;
70
+ --ef-color-surface-primary: #171a18;
71
+ --ef-color-surface-secondary: #202421;
72
+ --ef-color-text-heading: #f2efe7;
73
+ --ef-color-text-inverse: #171a18;
74
+ --ef-color-text-on-secondary-surface: #f2efe7;
75
+ --ef-color-text-primary: #f2efe7;
76
+ --ef-color-text-secondary: #e3e0d7;
77
+ }
78
+ }
79
+ [data-ef-theme="dark"] {
80
+ --ef-color-accent-primary: #a87e5e;
81
+ --ef-color-accent-secondary: #698d84;
82
+ --ef-color-border-functional: #e3e0d7;
83
+ --ef-color-border-subtle: #3a403c;
84
+ --ef-color-control-active: #a87e5e;
85
+ --ef-color-control-thumb: #f2efe7;
86
+ --ef-color-control-track: #686d68;
87
+ --ef-color-focus-gap: #171a18;
88
+ --ef-color-focus-ring: #f2efe7;
89
+ --ef-color-surface-inverse: #f2efe7;
90
+ --ef-color-surface-inverse-secondary: #e3e0d7;
91
+ --ef-color-surface-primary: #171a18;
92
+ --ef-color-surface-secondary: #202421;
93
+ --ef-color-text-heading: #f2efe7;
94
+ --ef-color-text-inverse: #171a18;
95
+ --ef-color-text-on-secondary-surface: #f2efe7;
96
+ --ef-color-text-primary: #f2efe7;
97
+ --ef-color-text-secondary: #e3e0d7;
98
+ }
99
+ }
@@ -0,0 +1,148 @@
1
+ # Forma Branding and Skinning
2
+
3
+ Forma treats branding and skinning as separate presentation contracts.
4
+
5
+ - A **brand** changes identity and brand-level design tokens.
6
+ - A **skin** changes presentation density/shape without changing identity.
7
+ - Neither contract owns application behavior or domain state.
8
+
9
+ ## Brand Manifest
10
+
11
+ Create a JSON manifest that conforms to `schemas/brand-manifest.schema.json`.
12
+ Repository-owned manifests live in `brands/*.brand.json`.
13
+
14
+ A manifest contains a stable brand ID, identity metadata, optional typography
15
+ and shape values, complete light/dark semantic colors, and optional application
16
+ terminology.
17
+
18
+ The manifest is data. Do not place CSS, script, credentials, or executable
19
+ configuration in it.
20
+
21
+ ## Build
22
+
23
+ Compile all repository brand manifests with:
24
+
25
+ ```bash
26
+ npm run brands:build
27
+ ```
28
+
29
+ The F# compiler writes static files to:
30
+
31
+ ```text
32
+ dist/brands/<brand-id>.css
33
+ dist/brands/index.json
34
+ ```
35
+
36
+ Invalid six-digit colors, unsafe font values, invalid dimensions, unsupported
37
+ schema versions, or insufficient required contrast fail the build.
38
+
39
+ ## Load and apply a brand
40
+
41
+ Load Forma first, then the desired generated brand CSS:
42
+
43
+ ```html
44
+ <link rel="stylesheet" href="/forma/all.css">
45
+ <link rel="stylesheet" href="/forma/brands/acme.css">
46
+ ```
47
+
48
+ Apply the brand at the document root:
49
+
50
+ ```html
51
+ <html data-ef-brand="acme">
52
+ ```
53
+
54
+ or to a subtree:
55
+
56
+ ```html
57
+ <section data-ef-brand="acme">
58
+ <!-- canonical Forma markup -->
59
+ </section>
60
+ ```
61
+
62
+ Because brands override the same documented `--ef-*` variables consumed by
63
+ Forma, canonical component markup does not change.
64
+
65
+ Multiple brand scopes can coexist on one page. This is useful for previews,
66
+ embedded products, partner portals, accessibility comparison, and design-system
67
+ testing.
68
+
69
+ ## Themes
70
+
71
+ Forma still uses `data-ef-theme="light"` and `data-ef-theme="dark"`.
72
+ The brand compiler emits both semantic maps and also honors operating-system dark
73
+ preference when an explicit theme is absent.
74
+
75
+ ```html
76
+ <section data-ef-brand="acme" data-ef-theme="dark">
77
+ ...
78
+ </section>
79
+ ```
80
+
81
+ Theme selection or persistence at runtime belongs to the consuming application,
82
+ normally through Limen. Forma only supplies the static presentation contract.
83
+
84
+ ## Skins
85
+
86
+ `dist/skins.css` defines the initial zero-runtime skin presets:
87
+
88
+ - `compact`
89
+ - `comfortable`
90
+ - `square`
91
+
92
+ Use a skin independently of brand:
93
+
94
+ ```html
95
+ <main data-ef-brand="acme" data-ef-skin="compact">
96
+ ...
97
+ </main>
98
+ ```
99
+
100
+ A skin must not change labels, identity, permissions, workflow, validation,
101
+ scoring, or domain state.
102
+
103
+ ## Terminology and assets
104
+
105
+ Brand terminology and identity assets are intentionally not converted into CSS.
106
+ Applications/build tooling consume those fields because they affect content and
107
+ metadata rather than component presentation.
108
+
109
+ This keeps a strong boundary:
110
+
111
+ ```text
112
+ Brand Manifest
113
+ ├─ identity / assets / terms -> application/build adapters
114
+ └─ presentation -> BrandCompiler -> scoped CSS variables
115
+
116
+ Skin
117
+ └─ presentation only -> skins.css
118
+
119
+ Application / Limen
120
+ └─ runtime selection, persistence, remote loading, preview behavior
121
+
122
+ Ordo / domain
123
+ └─ legal state and transitions
124
+ ```
125
+
126
+ ## Accessibility
127
+
128
+ The brand compiler currently validates the relationships that are most likely to
129
+ make a branded interface unreadable: primary and secondary text, text on
130
+ secondary surfaces, inverse text, primary/secondary accents, and focus rings.
131
+
132
+ A failed brand does not get a best-effort output. Fix the manifest and compile
133
+ again.
134
+
135
+ Forced-colors behavior and non-color state cues remain part of Forma's existing
136
+ component accessibility contract.
137
+
138
+ ## White-labeling rules for applications
139
+
140
+ Applications should not fork Forma component CSS just to implement customer
141
+ branding. Add or update a Brand Manifest and consume its generated CSS.
142
+
143
+ Arbitrary customer CSS is not the supported extension mechanism. Internal
144
+ component structure is not a theming API.
145
+
146
+ If a required presentation concept cannot be expressed through the current
147
+ manifest/token contract, record the gap in Forma and extend the public contract
148
+ deliberately.
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@echelon-foundry/design-system",
3
+ "version": "0.2.0-main.15.1",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "Zero-runtime HTML and CSS design system for Echelon Foundry applications.",
7
+ "sideEffects": [
8
+ "./dist/*.css",
9
+ "./dist/brands/*.css"
10
+ ],
11
+ "exports": {
12
+ "./tokens.css": "./dist/tokens.css",
13
+ "./foundations.css": "./dist/foundations.css",
14
+ "./components.css": "./dist/components.css",
15
+ "./all.css": "./dist/all.css",
16
+ "./patterns/*": "./dist/patterns/*",
17
+ "./assessment.css": "./dist/assessment.css",
18
+ "./skins.css": "./dist/skins.css",
19
+ "./brands/*": "./dist/brands/*",
20
+ "./brand-manifest.schema.json": "./schemas/brand-manifest.schema.json"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "patterns",
25
+ "schemas/brand-manifest.schema.json",
26
+ "docs/BRANDING.md"
27
+ ],
28
+ "scripts": {
29
+ "clean": "node tools/clean.mjs",
30
+ "tokens:build": "dotnet run --project tools/TokenCompiler/TokenCompiler.fsproj -- tokens/echelon.tokens.json dist/tokens.css",
31
+ "assets:build": "node tools/build-assets.mjs",
32
+ "build": "npm run clean && npm run tokens:build && npm run brands:build && npm run assets:build",
33
+ "test:tokens": "node --test tests/token-compiler.test.mjs",
34
+ "test:browser": "playwright test",
35
+ "test:a11y": "playwright test tests/browser/accessibility.spec.mjs",
36
+ "test:runtime": "node --test tests/zero-runtime.test.mjs",
37
+ "check": "npm run build && npm run test:tokens && npm run test:brands && npm run test:runtime && npm run test:package && npm run test:browser",
38
+ "site:build": "npm run build && node tools/build-site.mjs",
39
+ "site:test": "node --test tests/site-build.test.mjs",
40
+ "site:check": "npm run site:build && npm run site:test && npm run site:mobile",
41
+ "site:mobile": "playwright test --config=playwright.site.config.mjs",
42
+ "pack:verify": "npm run build && npm pack --dry-run",
43
+ "test:package": "node --test tests/package-contract.test.mjs",
44
+ "brands:build": "dotnet run --project tools/BrandCompiler/BrandCompiler.fsproj -- brands dist/brands",
45
+ "test:brands": "node --test tests/brand-compiler.test.mjs"
46
+ },
47
+ "devDependencies": {
48
+ "@axe-core/playwright": "4.13.0",
49
+ "@playwright/test": "1.63.0"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public",
53
+ "provenance": true
54
+ },
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "git+https://github.com/kemiller2002/forma.git"
58
+ },
59
+ "homepage": "https://forma.echelonfoundry.com/"
60
+ }
@@ -0,0 +1,8 @@
1
+ <aside class="ef-alert" role="status" data-tone="attention" data-ef-motion-weight="standard" data-ef-motion-entry>
2
+ <div class="ef-alert__icon" aria-hidden="true">!</div>
3
+ <div>
4
+ <h3 class="ef-alert__title">Review required</h3>
5
+ <p>Two values changed since this view was loaded. No update has been applied.</p>
6
+ </div>
7
+ <button type="button">Review changes</button>
8
+ </aside>
@@ -0,0 +1,24 @@
1
+ <fieldset class="ef-allocation">
2
+ <legend class="ef-allocation__legend">Distribute 10 points across these priorities.</legend>
3
+
4
+ <div class="ef-allocation__items">
5
+ <label class="ef-allocation__item">
6
+ <span>Reliability</span>
7
+ <input type="number" name="reliability" min="0" max="10" step="1" value="4" inputmode="numeric">
8
+ </label>
9
+ <label class="ef-allocation__item">
10
+ <span>Delivery speed</span>
11
+ <input type="number" name="delivery-speed" min="0" max="10" step="1" value="3" inputmode="numeric">
12
+ </label>
13
+ <label class="ef-allocation__item">
14
+ <span>Cost efficiency</span>
15
+ <input type="number" name="cost-efficiency" min="0" max="10" step="1" value="3" inputmode="numeric">
16
+ </label>
17
+ </div>
18
+
19
+ <div class="ef-allocation__total" data-ef-state="valid" aria-live="polite" aria-atomic="true">
20
+ <span>Total</span>
21
+ <output>10 / 10</output>
22
+ </div>
23
+ <p class="ef-field__description">Limen validates the aggregate total and renders the authoritative state.</p>
24
+ </fieldset>
@@ -0,0 +1,93 @@
1
+ # Feature Manifest — Assessment and workflow patterns
2
+
3
+ ## Purpose
4
+
5
+ Provide reusable semantic markup and CSS for assessment, decision, validation, and Ordo-style unresolved-work presentation without embedding application behavior.
6
+
7
+ ## Ownership
8
+
9
+ - State, including presentation state: native radio/checkbox/number/progress state plus application-rendered `data-ef-*` state
10
+ - Transitions / commands / messages: native HTML events only for declarative controls; ranking/allocation/rule-builder behavior belongs to Limen/application code
11
+ - Invariants and guards: semantic form grouping, accessible names, non-color state cues, special answer separation, zero-runtime boundary
12
+ - Capabilities / authority: none — Signal/Ordo/application owns applicability, scoring, validation, capabilities, obligations, and completion
13
+ - Important effects and effect contracts: none
14
+
15
+ ## Interfaces
16
+
17
+ ### Declarative patterns
18
+
19
+ - `.ef-question`
20
+ - `.ef-ordinal-scale`
21
+ - `.ef-choice-group`
22
+ - `.ef-special-choices`
23
+ - `.ef-validation-message`
24
+ - `.ef-validation-summary`
25
+ - `.ef-survey-progress`
26
+ - `.ef-obligation-panel`
27
+ - `.ef-binary-choice`
28
+ - `.ef-semantic-differential`
29
+ - `.ef-symbol-rating`
30
+ - `.ef-numeric-stepper`
31
+ - `.ef-range-entry`
32
+ - `.ef-choice--media`
33
+ - `.ef-matrix`
34
+ - `.ef-pairwise`
35
+ - `.ef-best-worst`
36
+ - `.ef-hierarchy`
37
+
38
+ ### Behavior-required visual contracts
39
+
40
+ - `.ef-ranking`
41
+ - `.ef-allocation` aggregate validation
42
+ - `.ef-rule-builder`
43
+ - graphical dual-thumb range interaction
44
+ - best/worst cross-column exclusion
45
+ - multi-choice cardinality/exclusive-option enforcement
46
+ - matrix global constraints
47
+ - hierarchical cascading/parent-child policy
48
+
49
+ ## Tests and verification
50
+
51
+ - browser behavior: `tests/browser/assessment.spec.mjs`
52
+ - automated accessibility: `tests/browser/accessibility.spec.mjs`
53
+ - zero-runtime boundary: `tests/zero-runtime.test.mjs`
54
+ - responsive ordinal presentation: browser test at narrow viewport
55
+
56
+ ## Dependencies
57
+
58
+ - allowed direct dependencies: semantic tokens, foundations, assessment CSS
59
+ - required composition context: consuming application supplies domain state and Limen behavior where documented
60
+
61
+ ## Modification boundaries
62
+
63
+ Normal:
64
+
65
+ - `patterns/question.html`
66
+ - `patterns/ordinal-scale.html`
67
+ - `patterns/choice-group.html`
68
+ - `patterns/special-choice.html`
69
+ - `patterns/validation-*.html`
70
+ - `patterns/survey-progress.html`
71
+ - `patterns/ranking.html`
72
+ - `patterns/allocation.html`
73
+ - `patterns/rule-builder.html`
74
+ - `patterns/obligation-panel.html`
75
+ - `src/styles/assessment.css`
76
+ - related tests/docs
77
+
78
+ Escalation required:
79
+
80
+ - adding executable behavior to the package;
81
+ - creating scoring semantics from presentation;
82
+ - replacing native radio/checkbox semantics;
83
+ - collapsing Unknown, Not Applicable, and ordinal values into one visual continuum;
84
+ - making drag the only ranking path;
85
+ - using a checkbox switch where Unanswered must remain distinct from false;
86
+ - treating NPS/Likert/star/icon labels as scoring authority;
87
+ - requiring horizontal scrolling as the only matrix mobile interaction.
88
+
89
+ ## Maintenance
90
+
91
+ - Owner: Echelon Foundry design system
92
+ - First demanding consumer: Echelon Signal
93
+ - Last checked against implementation: 2026-09-22
@@ -0,0 +1,21 @@
1
+ <fieldset class="ef-best-worst">
2
+ <legend class="ef-best-worst__legend">Choose the most important and least important item.</legend>
3
+ <p class="ef-field__description">One item must be Best and a different item must be Worst. Limen enforces the cross-column constraint.</p>
4
+
5
+ <div class="ef-best-worst__header" aria-hidden="true">
6
+ <span>Option</span><span>Best</span><span>Worst</span>
7
+ </div>
8
+
9
+ <div class="ef-best-worst__row">
10
+ <span id="bw-reliability">Reliability</span>
11
+ <label><input type="radio" name="best" value="reliability" aria-labelledby="bw-reliability bw-best-label"><span class="ef-sr-only" id="bw-best-label">Best</span></label>
12
+ <label><input type="radio" name="worst" value="reliability" aria-labelledby="bw-reliability bw-worst-label"><span class="ef-sr-only" id="bw-worst-label">Worst</span></label>
13
+ </div>
14
+ <div class="ef-best-worst__row">
15
+ <span id="bw-speed">Delivery speed</span>
16
+ <label><input type="radio" name="best" value="speed" aria-label="Delivery speed, Best"></label>
17
+ <label><input type="radio" name="worst" value="speed" aria-label="Delivery speed, Worst"></label>
18
+ </div>
19
+
20
+ <p class="ef-best-worst__status" data-ef-state="incomplete" aria-live="polite">Choose one Best and one Worst.</p>
21
+ </fieldset>
@@ -0,0 +1,15 @@
1
+ <fieldset class="ef-binary-choice">
2
+ <legend class="ef-binary-choice__legend">Is automated deployment currently in use?</legend>
3
+ <p class="ef-field__description" id="binary-choice-help">Choose one response. An unanswered question remains distinct from No.</p>
4
+
5
+ <div class="ef-binary-choice__options" aria-describedby="binary-choice-help">
6
+ <label class="ef-binary-option">
7
+ <input type="radio" name="automated-deployment" value="yes" required>
8
+ <span>Yes</span>
9
+ </label>
10
+ <label class="ef-binary-option">
11
+ <input type="radio" name="automated-deployment" value="no">
12
+ <span>No</span>
13
+ </label>
14
+ </div>
15
+ </fieldset>
@@ -0,0 +1,13 @@
1
+ <label class="ef-checkbox" data-ef-motion-weight="standard">
2
+ <input
3
+ class="ef-checkbox__input"
4
+ type="checkbox"
5
+ name="audit-log"
6
+ value="enabled"
7
+ aria-describedby="audit-log-description">
8
+ <span class="ef-checkbox__box" aria-hidden="true"></span>
9
+ <span class="ef-checkbox__text">
10
+ <span class="ef-checkbox__label">Record audit events</span>
11
+ <span class="ef-checkbox__description" id="audit-log-description">Include this action in the audit trail.</span>
12
+ </span>
13
+ </label>
@@ -0,0 +1,27 @@
1
+ <fieldset class="ef-choice-group">
2
+ <legend class="ef-choice-group__legend">Which environment is most representative?</legend>
3
+
4
+ <label class="ef-choice">
5
+ <input type="radio" name="environment" value="cloud" required>
6
+ <span class="ef-choice__content">
7
+ <strong>Cloud</strong>
8
+ <span>Primarily hosted cloud infrastructure.</span>
9
+ </span>
10
+ </label>
11
+
12
+ <label class="ef-choice">
13
+ <input type="radio" name="environment" value="hybrid">
14
+ <span class="ef-choice__content">
15
+ <strong>Hybrid</strong>
16
+ <span>Cloud and on-premises infrastructure.</span>
17
+ </span>
18
+ </label>
19
+
20
+ <label class="ef-choice">
21
+ <input type="radio" name="environment" value="on-premises">
22
+ <span class="ef-choice__content">
23
+ <strong>On-premises</strong>
24
+ <span>Primarily locally hosted infrastructure.</span>
25
+ </span>
26
+ </label>
27
+ </fieldset>