@echelon-foundry/design-system 0.2.0 → 0.3.0-main.216.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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -0
  3. package/dist/all.css +5537 -841
  4. package/dist/assessment.css +55 -12
  5. package/dist/build-metrics.json +181 -5
  6. package/dist/components.css +2965 -36
  7. package/dist/foundations.css +90 -0
  8. package/dist/marketing/forma-all.css +8162 -0
  9. package/dist/marketing/forma-echelon-marketing.css +2109 -0
  10. package/dist/marketing/forma-marketing-theme-echelon.css +163 -0
  11. package/dist/marketing/forma-marketing.css +1947 -0
  12. package/dist/marketing/forma-marketing.manifest.json +52 -0
  13. package/dist/marketing/forma-marketing.sha256 +4 -0
  14. package/dist/marketing.css +1198 -0
  15. package/dist/patterns/active-filter-summary.html +10 -0
  16. package/dist/patterns/attention-path.html +29 -0
  17. package/dist/patterns/badge.html +9 -0
  18. package/dist/patterns/callout.html +23 -0
  19. package/dist/patterns/card-grid.html +25 -0
  20. package/dist/patterns/character-grid-3270.html +39 -0
  21. package/dist/patterns/character-grid-field.html +21 -0
  22. package/dist/patterns/character-grid-keys.html +20 -0
  23. package/dist/patterns/character-grid-reveal.html +16 -0
  24. package/dist/patterns/character-grid-selection.html +30 -0
  25. package/dist/patterns/character-grid-status.html +11 -0
  26. package/dist/patterns/character-grid-workflow.html +147 -0
  27. package/dist/patterns/character-grid.html +16 -0
  28. package/dist/patterns/cluster.html +5 -0
  29. package/dist/patterns/code-sample.html +9 -0
  30. package/dist/patterns/command-group.html +6 -0
  31. package/dist/patterns/comparison-grid.html +7 -0
  32. package/dist/patterns/comparison-pairs.html +13 -0
  33. package/dist/patterns/cta.html +12 -0
  34. package/dist/patterns/dense-ledger.html +7 -0
  35. package/dist/patterns/diagnostic-status.html +7 -0
  36. package/dist/patterns/diagram.html +49 -0
  37. package/dist/patterns/documentation-layout.html +18 -0
  38. package/dist/patterns/emphasis-budget.html +21 -0
  39. package/dist/patterns/entry-index.html +16 -0
  40. package/dist/patterns/evidence-relationship.html +1 -0
  41. package/dist/patterns/facts.html +7 -0
  42. package/dist/patterns/fault-banner.html +19 -0
  43. package/dist/patterns/fault-blocking.html +25 -0
  44. package/dist/patterns/fault-details.html +11 -0
  45. package/dist/patterns/fault-inline.html +17 -0
  46. package/dist/patterns/fault-notification.html +20 -0
  47. package/dist/patterns/fault-reference.html +5 -0
  48. package/dist/patterns/fault-summary.html +20 -0
  49. package/dist/patterns/fault.html +17 -0
  50. package/dist/patterns/feed-item.html +12 -0
  51. package/dist/patterns/focus-stage.html +4 -0
  52. package/dist/patterns/frame.html +4 -0
  53. package/dist/patterns/freshness.html +1 -0
  54. package/dist/patterns/handoff-summary.html +1 -0
  55. package/dist/patterns/hero.html +17 -0
  56. package/dist/patterns/hierarchy-tree.html +11 -0
  57. package/dist/patterns/identifier.html +9 -0
  58. package/dist/patterns/landmark-region.html +4 -0
  59. package/dist/patterns/lane-board.html +10 -0
  60. package/dist/patterns/marketing-shell.html +40 -0
  61. package/dist/patterns/measure.html +4 -0
  62. package/dist/patterns/metric-value-change.html +9 -0
  63. package/dist/patterns/mosaic.html +6 -0
  64. package/dist/patterns/navigation-shell.html +8 -0
  65. package/dist/patterns/overflow-command-disclosure.html +6 -0
  66. package/dist/patterns/overview-disclosure.html +12 -0
  67. package/dist/patterns/path-summary.html +8 -0
  68. package/dist/patterns/priority-stack.html +4 -0
  69. package/dist/patterns/progress-bar.html +15 -0
  70. package/dist/patterns/prose.html +9 -0
  71. package/dist/patterns/rail.html +4 -0
  72. package/dist/patterns/recovery-actions.html +5 -0
  73. package/dist/patterns/relationship-index.html +8 -0
  74. package/dist/patterns/reorder-states.html +31 -0
  75. package/dist/patterns/resizable-split-pane.html +11 -0
  76. package/dist/patterns/responsive-grid.html +5 -0
  77. package/dist/patterns/scope-trail.html +1 -0
  78. package/dist/patterns/scroll-progress.html +6 -0
  79. package/dist/patterns/section-heading.html +12 -0
  80. package/dist/patterns/security-blockers.html +3 -0
  81. package/dist/patterns/security-evidence-age.html +1 -0
  82. package/dist/patterns/security-evidence-chain.html +2 -0
  83. package/dist/patterns/security-exception.html +2 -0
  84. package/dist/patterns/security-invariant-result.html +1 -0
  85. package/dist/patterns/security-posture.html +22 -0
  86. package/dist/patterns/security-state-matrix.html +5 -0
  87. package/dist/patterns/security-trend.html +1 -0
  88. package/dist/patterns/security-unknown.html +2 -0
  89. package/dist/patterns/sidebar.html +4 -0
  90. package/dist/patterns/site-footer.html +12 -0
  91. package/dist/patterns/site-header.html +18 -0
  92. package/dist/patterns/spatial-canvas.html +13 -0
  93. package/dist/patterns/spinner.html +4 -0
  94. package/dist/patterns/split-pane.html +4 -0
  95. package/dist/patterns/stack.html +5 -0
  96. package/dist/patterns/state-survivability.html +19 -0
  97. package/dist/patterns/steps.html +8 -0
  98. package/dist/patterns/switcher.html +4 -0
  99. package/dist/patterns/tooltip.html +48 -0
  100. package/dist/patterns/verification-frame.html +22 -0
  101. package/dist/patterns/workspace-shell.html +6 -0
  102. package/dist/tokens.css +436 -1
  103. package/docs/BRANDING.md +6 -1
  104. package/docs/MARKETING-SITES.md +321 -0
  105. package/figma/component-contracts.json +1544 -0
  106. package/package.json +34 -8
  107. package/patterns/active-filter-summary.html +10 -0
  108. package/patterns/aegis-faults.manifest.md +81 -0
  109. package/patterns/attention-path.html +29 -0
  110. package/patterns/badge.html +9 -0
  111. package/patterns/callout.html +23 -0
  112. package/patterns/card-grid.html +25 -0
  113. package/patterns/character-grid-3270.html +39 -0
  114. package/patterns/character-grid-field.html +21 -0
  115. package/patterns/character-grid-keys.html +20 -0
  116. package/patterns/character-grid-reveal.html +16 -0
  117. package/patterns/character-grid-selection.html +30 -0
  118. package/patterns/character-grid-status.html +11 -0
  119. package/patterns/character-grid-workflow.html +147 -0
  120. package/patterns/character-grid.html +16 -0
  121. package/patterns/cluster.html +5 -0
  122. package/patterns/code-sample.html +9 -0
  123. package/patterns/command-group.html +6 -0
  124. package/patterns/comparison-grid.html +7 -0
  125. package/patterns/comparison-pairs.html +13 -0
  126. package/patterns/cta.html +12 -0
  127. package/patterns/dense-ledger.html +7 -0
  128. package/patterns/diagnostic-status.html +7 -0
  129. package/patterns/diagram.html +49 -0
  130. package/patterns/documentation-layout.html +18 -0
  131. package/patterns/emphasis-budget.html +21 -0
  132. package/patterns/entry-index.html +16 -0
  133. package/patterns/evidence-relationship.html +1 -0
  134. package/patterns/facts.html +7 -0
  135. package/patterns/fault-banner.html +19 -0
  136. package/patterns/fault-blocking.html +25 -0
  137. package/patterns/fault-details.html +11 -0
  138. package/patterns/fault-inline.html +17 -0
  139. package/patterns/fault-notification.html +20 -0
  140. package/patterns/fault-reference.html +5 -0
  141. package/patterns/fault-summary.html +20 -0
  142. package/patterns/fault.html +17 -0
  143. package/patterns/feed-item.html +12 -0
  144. package/patterns/focus-stage.html +4 -0
  145. package/patterns/frame.html +4 -0
  146. package/patterns/freshness.html +1 -0
  147. package/patterns/handoff-summary.html +1 -0
  148. package/patterns/hero.html +17 -0
  149. package/patterns/hierarchy-tree.html +11 -0
  150. package/patterns/identifier.html +9 -0
  151. package/patterns/landmark-region.html +4 -0
  152. package/patterns/lane-board.html +10 -0
  153. package/patterns/manifest.md +2 -0
  154. package/patterns/marketing-shell.html +40 -0
  155. package/patterns/measure.html +4 -0
  156. package/patterns/metric-value-change.html +9 -0
  157. package/patterns/mosaic.html +6 -0
  158. package/patterns/navigation-shell.html +8 -0
  159. package/patterns/overflow-command-disclosure.html +6 -0
  160. package/patterns/overview-disclosure.html +12 -0
  161. package/patterns/path-summary.html +8 -0
  162. package/patterns/priority-stack.html +4 -0
  163. package/patterns/progress-bar.html +15 -0
  164. package/patterns/prose.html +9 -0
  165. package/patterns/rail.html +4 -0
  166. package/patterns/recovery-actions.html +5 -0
  167. package/patterns/relationship-index.html +8 -0
  168. package/patterns/reorder-states.html +31 -0
  169. package/patterns/resizable-split-pane.html +11 -0
  170. package/patterns/responsive-grid.html +5 -0
  171. package/patterns/scope-trail.html +1 -0
  172. package/patterns/scroll-progress.html +6 -0
  173. package/patterns/section-heading.html +12 -0
  174. package/patterns/security-blockers.html +3 -0
  175. package/patterns/security-evidence-age.html +1 -0
  176. package/patterns/security-evidence-chain.html +2 -0
  177. package/patterns/security-exception.html +2 -0
  178. package/patterns/security-invariant-result.html +1 -0
  179. package/patterns/security-posture.html +22 -0
  180. package/patterns/security-posture.manifest.md +20 -0
  181. package/patterns/security-state-matrix.html +5 -0
  182. package/patterns/security-trend.html +1 -0
  183. package/patterns/security-unknown.html +2 -0
  184. package/patterns/sidebar.html +4 -0
  185. package/patterns/site-footer.html +12 -0
  186. package/patterns/site-header.html +18 -0
  187. package/patterns/spatial-canvas.html +13 -0
  188. package/patterns/spinner.html +4 -0
  189. package/patterns/split-pane.html +4 -0
  190. package/patterns/stack.html +5 -0
  191. package/patterns/state-survivability.html +19 -0
  192. package/patterns/steps.html +8 -0
  193. package/patterns/switcher.html +4 -0
  194. package/patterns/tooltip.html +48 -0
  195. package/patterns/verification-frame.html +22 -0
  196. package/patterns/workspace-shell.html +6 -0
  197. package/schemas/brand-manifest.schema.json +17 -3
  198. package/tokens/echelon.tokens.json +2801 -0
@@ -0,0 +1,1947 @@
1
+ /*! Forma 0.3.0 | forma-marketing.css | bundle echelon-marketing
2
+ Brand-neutral marketing layer: core tokens, role defaults, Forma foundations, marketing foundations, components, and layouts.
3
+ Generated by tools/PresentationBundler. Do not edit; pin by version and sha256. */
4
+
5
+ /* --- source: dist/tokens.css --- */
6
+ /* Generated from echelon.tokens.json. Do not edit directly. */
7
+ @layer echelon.tokens {
8
+ :root {
9
+ --ef-primitive-border-width-accent: 4px;
10
+ --ef-primitive-border-width-thick: 2px;
11
+ --ef-primitive-border-width-thin: 1px;
12
+ --ef-primitive-color-amber-light: #d99a55;
13
+ --ef-primitive-color-analog-blue: #315f8c;
14
+ --ef-primitive-color-analog-teal: #286c68;
15
+ --ef-primitive-color-black: #000000;
16
+ --ef-primitive-color-carbon: #171a18;
17
+ --ef-primitive-color-clinical: #f8fafb;
18
+ --ef-primitive-color-clinical-muted: #50636d;
19
+ --ef-primitive-color-clinical-secondary: #e6edf1;
20
+ --ef-primitive-color-clinical-text: #17242b;
21
+ --ef-primitive-color-comp-blue: #175f8f;
22
+ --ef-primitive-color-comp-rust: #9a3f19;
23
+ --ef-primitive-color-deep-slate: #12191d;
24
+ --ef-primitive-color-earth-bg: #f3eadc;
25
+ --ef-primitive-color-earth-green: #356044;
26
+ --ef-primitive-color-earth-surface: #dfcfb8;
27
+ --ef-primitive-color-earth-text: #29231c;
28
+ --ef-primitive-color-editorial-bg: #f6f4ef;
29
+ --ef-primitive-color-editorial-surface: #e7e3da;
30
+ --ef-primitive-color-forest: #285c45;
31
+ --ef-primitive-color-forged-iron: #3a403c;
32
+ --ef-primitive-color-foundry-charcoal: #202421;
33
+ --ef-primitive-color-graphite: #686d68;
34
+ --ef-primitive-color-ice: #e8f1f4;
35
+ --ef-primitive-color-ink: #211d18;
36
+ --ef-primitive-color-institutional-bg: #f4f7f8;
37
+ --ef-primitive-color-institutional-blue: #245d7a;
38
+ --ef-primitive-color-institutional-surface: #dde6e9;
39
+ --ef-primitive-color-institutional-text: #17252b;
40
+ --ef-primitive-color-mono-accent: #3b5f55;
41
+ --ef-primitive-color-muted-plum: #70405c;
42
+ --ef-primitive-color-muted-teal: #356b64;
43
+ --ef-primitive-color-nature-bg: #f1f0e5;
44
+ --ef-primitive-color-nature-blue: #315e75;
45
+ --ef-primitive-color-nature-green: #315f3d;
46
+ --ef-primitive-color-nature-surface: #dce2cf;
47
+ --ef-primitive-color-nature-text: #20281f;
48
+ --ef-primitive-color-navy: #244f73;
49
+ --ef-primitive-color-neutral-100: #eeeeee;
50
+ --ef-primitive-color-neutral-200: #d8d8d8;
51
+ --ef-primitive-color-neutral-650: #555555;
52
+ --ef-primitive-color-neutral-800: #303030;
53
+ --ef-primitive-color-neutral-950: #161616;
54
+ --ef-primitive-color-ops-blue: #315f8c;
55
+ --ef-primitive-color-ops-red: #9c2f25;
56
+ --ef-primitive-color-oxide-bronze: #905831;
57
+ --ef-primitive-color-oxide-bronze-deep: #74461f;
58
+ --ef-primitive-color-oxide-bronze-light: #a87e5e;
59
+ --ef-primitive-color-oxide-bronze-pale: #c9a07f;
60
+ --ef-primitive-color-paper: #f7f2e7;
61
+ --ef-primitive-color-paper-muted: #e7dece;
62
+ --ef-primitive-color-parchment: #f2efe7;
63
+ --ef-primitive-color-parchment-light: #f8f6f1;
64
+ --ef-primitive-color-signal-blue: #005ea8;
65
+ --ef-primitive-color-signal-cyan: #006b75;
66
+ --ef-primitive-color-slate-surface: #202a30;
67
+ --ef-primitive-color-split-blue: #175f8f;
68
+ --ef-primitive-color-split-plum: #7a3f70;
69
+ --ef-primitive-color-split-rust: #93451e;
70
+ --ef-primitive-color-status-danger: #a13a2c;
71
+ --ef-primitive-color-status-danger-light: #ef9a8b;
72
+ --ef-primitive-color-status-info: #2d5f86;
73
+ --ef-primitive-color-status-info-light: #90b9dc;
74
+ --ef-primitive-color-status-success: #2e6a45;
75
+ --ef-primitive-color-status-success-light: #8cc49f;
76
+ --ef-primitive-color-status-warning: #86560f;
77
+ --ef-primitive-color-status-warning-light: #ddb266;
78
+ --ef-primitive-color-stone: #e3e0d7;
79
+ --ef-primitive-color-tech-amber: #d29a58;
80
+ --ef-primitive-color-tech-bg: #101619;
81
+ --ef-primitive-color-tech-cyan: #63a8b2;
82
+ --ef-primitive-color-tech-surface: #1d272c;
83
+ --ef-primitive-color-tech-text: #e7eef0;
84
+ --ef-primitive-color-verdigris: #47756b;
85
+ --ef-primitive-color-verdigris-light: #698d84;
86
+ --ef-primitive-color-white: #ffffff;
87
+ --ef-primitive-focus-halo-width: 5px;
88
+ --ef-primitive-focus-ring-offset: 2px;
89
+ --ef-primitive-focus-ring-width: 3px;
90
+ --ef-primitive-font-family-display: Newsreader, Georgia, serif;
91
+ --ef-primitive-font-family-mono: "IBM Plex Mono", ui-monospace, monospace;
92
+ --ef-primitive-font-family-sans: Manrope, system-ui, sans-serif;
93
+ --ef-primitive-font-size-2xl: 2rem;
94
+ --ef-primitive-font-size-2xs: 0.6875rem;
95
+ --ef-primitive-font-size-3xl: 2.5rem;
96
+ --ef-primitive-font-size-fluid-display-1: clamp(2.5rem, 1.75rem + 6vw, 7.25rem);
97
+ --ef-primitive-font-size-fluid-display-2: clamp(2rem, 1.25rem + 3.6vw, 4.5rem);
98
+ --ef-primitive-font-size-fluid-display-3: clamp(1.5rem, 1rem + 1.6vw, 2.4rem);
99
+ --ef-primitive-font-size-fluid-lead: clamp(1.125rem, 0.875rem + 0.85vw, 1.5rem);
100
+ --ef-primitive-font-size-lg: 1.25rem;
101
+ --ef-primitive-font-size-md: 1rem;
102
+ --ef-primitive-font-size-sm: 0.875rem;
103
+ --ef-primitive-font-size-xl: 1.5rem;
104
+ --ef-primitive-font-size-xs: 0.75rem;
105
+ --ef-primitive-font-weight-bold: 700;
106
+ --ef-primitive-font-weight-medium: 500;
107
+ --ef-primitive-font-weight-regular: 400;
108
+ --ef-primitive-font-weight-semibold: 600;
109
+ --ef-primitive-letter-spacing-normal: 0em;
110
+ --ef-primitive-letter-spacing-tight: -0.035em;
111
+ --ef-primitive-letter-spacing-wide: 0.09em;
112
+ --ef-primitive-line-height-display: 1;
113
+ --ef-primitive-line-height-normal: 1.5;
114
+ --ef-primitive-line-height-relaxed: 1.65;
115
+ --ef-primitive-line-height-snug: 1.25;
116
+ --ef-primitive-motion-duration-fast: 120ms;
117
+ --ef-primitive-motion-duration-instant: 0ms;
118
+ --ef-primitive-motion-duration-slow: 280ms;
119
+ --ef-primitive-motion-duration-standard: 180ms;
120
+ --ef-primitive-motion-easing-enter: cubic-bezier(0, 0, 0.2, 1);
121
+ --ef-primitive-motion-easing-exit: cubic-bezier(0.4, 0, 1, 1);
122
+ --ef-primitive-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
123
+ --ef-primitive-radius-medium: 8px;
124
+ --ef-primitive-radius-none: 0px;
125
+ --ef-primitive-radius-pill: 999px;
126
+ --ef-primitive-radius-small: 4px;
127
+ --ef-primitive-shadow-raised: 0px 1px 2px 0px rgb(23 26 24 / 0.08), 0px 8px 24px -8px rgb(23 26 24 / 0.08);
128
+ --ef-primitive-size-container-max: 90rem;
129
+ --ef-primitive-size-container-narrow: 45rem;
130
+ --ef-primitive-size-container-standard: 64rem;
131
+ --ef-primitive-size-container-wide: 75rem;
132
+ --ef-primitive-size-fluid-block-space: clamp(1.25rem, 0.75rem + 1.5vw, 2.25rem);
133
+ --ef-primitive-size-fluid-gutter: clamp(1rem, 4vw, 4.5rem);
134
+ --ef-primitive-size-fluid-section-space: clamp(4rem, 2rem + 6vw, 10rem);
135
+ --ef-primitive-size-measure: 72ch;
136
+ --ef-primitive-size-measure-narrow: 62ch;
137
+ --ef-primitive-size-target-min: 2.75rem;
138
+ --ef-primitive-space-1: 0.25rem;
139
+ --ef-primitive-space-2: 0.5rem;
140
+ --ef-primitive-space-3: 0.75rem;
141
+ --ef-primitive-space-4: 1rem;
142
+ --ef-primitive-space-5: 1.25rem;
143
+ --ef-primitive-space-6: 1.5rem;
144
+ --ef-primitive-space-7: 2rem;
145
+ --ef-primitive-space-8: 3rem;
146
+ --ef-primitive-spacing-1: 4px;
147
+ --ef-primitive-spacing-10: 128px;
148
+ --ef-primitive-spacing-2: 8px;
149
+ --ef-primitive-spacing-3: 12px;
150
+ --ef-primitive-spacing-4: 16px;
151
+ --ef-primitive-spacing-5: 24px;
152
+ --ef-primitive-spacing-6: 32px;
153
+ --ef-primitive-spacing-7: 48px;
154
+ --ef-primitive-spacing-8: 64px;
155
+ --ef-primitive-spacing-9: 96px;
156
+ }
157
+ :root, [data-ef-theme="light"] {
158
+ --ef-color-accent-primary: #905831;
159
+ --ef-color-accent-secondary: #47756b;
160
+ --ef-color-border-functional: #3a403c;
161
+ --ef-color-border-subtle: #e3e0d7;
162
+ --ef-color-control-active: #905831;
163
+ --ef-color-control-thumb: #f2efe7;
164
+ --ef-color-control-track: #686d68;
165
+ --ef-color-focus-gap: #f2efe7;
166
+ --ef-color-focus-ring: #171a18;
167
+ --ef-color-surface-inverse: #202421;
168
+ --ef-color-surface-inverse-secondary: #3a403c;
169
+ --ef-color-surface-primary: #f2efe7;
170
+ --ef-color-surface-secondary: #e3e0d7;
171
+ --ef-color-text-heading: #202421;
172
+ --ef-color-text-inverse: #f2efe7;
173
+ --ef-color-text-on-secondary-surface: #3a403c;
174
+ --ef-color-text-primary: #171a18;
175
+ --ef-color-text-secondary: #686d68;
176
+ }
177
+ @media (prefers-color-scheme: dark) {
178
+ :root:not([data-ef-theme]) {
179
+ --ef-color-accent-primary: #a87e5e;
180
+ --ef-color-accent-secondary: #698d84;
181
+ --ef-color-border-functional: #e3e0d7;
182
+ --ef-color-border-subtle: #3a403c;
183
+ --ef-color-control-active: #a87e5e;
184
+ --ef-color-control-thumb: #f2efe7;
185
+ --ef-color-control-track: #686d68;
186
+ --ef-color-focus-gap: #171a18;
187
+ --ef-color-focus-ring: #f2efe7;
188
+ --ef-color-surface-inverse: #f2efe7;
189
+ --ef-color-surface-inverse-secondary: #e3e0d7;
190
+ --ef-color-surface-primary: #171a18;
191
+ --ef-color-surface-secondary: #202421;
192
+ --ef-color-text-heading: #f2efe7;
193
+ --ef-color-text-inverse: #171a18;
194
+ --ef-color-text-on-secondary-surface: #f2efe7;
195
+ --ef-color-text-primary: #f2efe7;
196
+ --ef-color-text-secondary: #e3e0d7;
197
+ }
198
+ }
199
+ [data-ef-theme="accent-neutral"] {
200
+ --ef-color-accent-primary: #005ea8;
201
+ --ef-color-accent-secondary: #006b75;
202
+ --ef-color-border-functional: #555555;
203
+ --ef-color-border-subtle: #d8d8d8;
204
+ --ef-color-control-active: #005ea8;
205
+ --ef-color-control-thumb: #ffffff;
206
+ --ef-color-control-track: #555555;
207
+ --ef-color-focus-gap: #ffffff;
208
+ --ef-color-focus-ring: #005ea8;
209
+ --ef-color-surface-inverse: #161616;
210
+ --ef-color-surface-inverse-secondary: #303030;
211
+ --ef-color-surface-primary: #ffffff;
212
+ --ef-color-surface-secondary: #eeeeee;
213
+ --ef-color-text-heading: #161616;
214
+ --ef-color-text-inverse: #ffffff;
215
+ --ef-color-text-on-secondary-surface: #303030;
216
+ --ef-color-text-primary: #161616;
217
+ --ef-color-text-secondary: #555555;
218
+ }
219
+ [data-ef-theme="analogous-cohesive"] {
220
+ --ef-color-accent-primary: #315f8c;
221
+ --ef-color-accent-secondary: #286c68;
222
+ --ef-color-border-functional: #555555;
223
+ --ef-color-border-subtle: #d8d8d8;
224
+ --ef-color-control-active: #315f8c;
225
+ --ef-color-control-thumb: #ffffff;
226
+ --ef-color-control-track: #555555;
227
+ --ef-color-focus-gap: #ffffff;
228
+ --ef-color-focus-ring: #315f8c;
229
+ --ef-color-surface-inverse: #161616;
230
+ --ef-color-surface-inverse-secondary: #303030;
231
+ --ef-color-surface-primary: #ffffff;
232
+ --ef-color-surface-secondary: #eeeeee;
233
+ --ef-color-text-heading: #161616;
234
+ --ef-color-text-inverse: #ffffff;
235
+ --ef-color-text-on-secondary-surface: #303030;
236
+ --ef-color-text-primary: #161616;
237
+ --ef-color-text-secondary: #555555;
238
+ }
239
+ [data-ef-theme="clinical-light"] {
240
+ --ef-color-accent-primary: #005ea8;
241
+ --ef-color-accent-secondary: #006b75;
242
+ --ef-color-border-functional: #50636d;
243
+ --ef-color-border-subtle: #e6edf1;
244
+ --ef-color-control-active: #005ea8;
245
+ --ef-color-control-thumb: #ffffff;
246
+ --ef-color-control-track: #50636d;
247
+ --ef-color-focus-gap: #f8fafb;
248
+ --ef-color-focus-ring: #005ea8;
249
+ --ef-color-surface-inverse: #17242b;
250
+ --ef-color-surface-inverse-secondary: #303030;
251
+ --ef-color-surface-primary: #f8fafb;
252
+ --ef-color-surface-secondary: #e6edf1;
253
+ --ef-color-text-heading: #17242b;
254
+ --ef-color-text-inverse: #f8fafb;
255
+ --ef-color-text-on-secondary-surface: #17242b;
256
+ --ef-color-text-primary: #17242b;
257
+ --ef-color-text-secondary: #50636d;
258
+ }
259
+ [data-ef-theme="complementary-energy"] {
260
+ --ef-color-accent-primary: #175f8f;
261
+ --ef-color-accent-secondary: #9a3f19;
262
+ --ef-color-border-functional: #555555;
263
+ --ef-color-border-subtle: #d8d8d8;
264
+ --ef-color-control-active: #175f8f;
265
+ --ef-color-control-thumb: #ffffff;
266
+ --ef-color-control-track: #555555;
267
+ --ef-color-focus-gap: #ffffff;
268
+ --ef-color-focus-ring: #175f8f;
269
+ --ef-color-surface-inverse: #161616;
270
+ --ef-color-surface-inverse-secondary: #303030;
271
+ --ef-color-surface-primary: #ffffff;
272
+ --ef-color-surface-secondary: #eeeeee;
273
+ --ef-color-text-heading: #161616;
274
+ --ef-color-text-inverse: #ffffff;
275
+ --ef-color-text-on-secondary-surface: #303030;
276
+ --ef-color-text-primary: #161616;
277
+ --ef-color-text-secondary: #555555;
278
+ }
279
+ [data-ef-theme="cool-institutional"] {
280
+ --ef-color-accent-primary: #245d7a;
281
+ --ef-color-accent-secondary: #006b75;
282
+ --ef-color-border-functional: #50636d;
283
+ --ef-color-border-subtle: #dde6e9;
284
+ --ef-color-control-active: #245d7a;
285
+ --ef-color-control-thumb: #ffffff;
286
+ --ef-color-control-track: #50636d;
287
+ --ef-color-focus-gap: #f4f7f8;
288
+ --ef-color-focus-ring: #245d7a;
289
+ --ef-color-surface-inverse: #17252b;
290
+ --ef-color-surface-inverse-secondary: #303030;
291
+ --ef-color-surface-primary: #f4f7f8;
292
+ --ef-color-surface-secondary: #dde6e9;
293
+ --ef-color-text-heading: #17252b;
294
+ --ef-color-text-inverse: #f4f7f8;
295
+ --ef-color-text-on-secondary-surface: #17252b;
296
+ --ef-color-text-primary: #17252b;
297
+ --ef-color-text-secondary: #50636d;
298
+ }
299
+ [data-ef-theme="dark"] {
300
+ --ef-color-accent-primary: #a87e5e;
301
+ --ef-color-accent-secondary: #698d84;
302
+ --ef-color-border-functional: #e3e0d7;
303
+ --ef-color-border-subtle: #3a403c;
304
+ --ef-color-control-active: #a87e5e;
305
+ --ef-color-control-thumb: #f2efe7;
306
+ --ef-color-control-track: #686d68;
307
+ --ef-color-focus-gap: #171a18;
308
+ --ef-color-focus-ring: #f2efe7;
309
+ --ef-color-surface-inverse: #f2efe7;
310
+ --ef-color-surface-inverse-secondary: #e3e0d7;
311
+ --ef-color-surface-primary: #171a18;
312
+ --ef-color-surface-secondary: #202421;
313
+ --ef-color-text-heading: #f2efe7;
314
+ --ef-color-text-inverse: #171a18;
315
+ --ef-color-text-on-secondary-surface: #f2efe7;
316
+ --ef-color-text-primary: #f2efe7;
317
+ --ef-color-text-secondary: #e3e0d7;
318
+ }
319
+ [data-ef-theme="dark-restrained"] {
320
+ --ef-color-accent-primary: #d99a55;
321
+ --ef-color-accent-secondary: #698d84;
322
+ --ef-color-border-functional: #e3e0d7;
323
+ --ef-color-border-subtle: #3a403c;
324
+ --ef-color-control-active: #d99a55;
325
+ --ef-color-control-thumb: #e8f1f4;
326
+ --ef-color-control-track: #686d68;
327
+ --ef-color-focus-gap: #12191d;
328
+ --ef-color-focus-ring: #e8f1f4;
329
+ --ef-color-surface-inverse: #e8f1f4;
330
+ --ef-color-surface-inverse-secondary: #e3e0d7;
331
+ --ef-color-surface-primary: #12191d;
332
+ --ef-color-surface-secondary: #202a30;
333
+ --ef-color-text-heading: #e8f1f4;
334
+ --ef-color-text-inverse: #12191d;
335
+ --ef-color-text-on-secondary-surface: #e8f1f4;
336
+ --ef-color-text-primary: #e8f1f4;
337
+ --ef-color-text-secondary: #e3e0d7;
338
+ }
339
+ [data-ef-theme="dark-technical"] {
340
+ --ef-color-accent-primary: #63a8b2;
341
+ --ef-color-accent-secondary: #d29a58;
342
+ --ef-color-border-functional: #e3e0d7;
343
+ --ef-color-border-subtle: #3a403c;
344
+ --ef-color-control-active: #63a8b2;
345
+ --ef-color-control-thumb: #e7eef0;
346
+ --ef-color-control-track: #686d68;
347
+ --ef-color-focus-gap: #101619;
348
+ --ef-color-focus-ring: #e7eef0;
349
+ --ef-color-surface-inverse: #e7eef0;
350
+ --ef-color-surface-inverse-secondary: #e3e0d7;
351
+ --ef-color-surface-primary: #101619;
352
+ --ef-color-surface-secondary: #1d272c;
353
+ --ef-color-text-heading: #e7eef0;
354
+ --ef-color-text-inverse: #101619;
355
+ --ef-color-text-on-secondary-surface: #e7eef0;
356
+ --ef-color-text-primary: #e7eef0;
357
+ --ef-color-text-secondary: #e3e0d7;
358
+ }
359
+ [data-ef-theme="high-contrast"] {
360
+ --ef-color-accent-primary: #000000;
361
+ --ef-color-accent-secondary: #303030;
362
+ --ef-color-border-functional: #000000;
363
+ --ef-color-border-subtle: #d8d8d8;
364
+ --ef-color-control-active: #000000;
365
+ --ef-color-control-thumb: #ffffff;
366
+ --ef-color-control-track: #555555;
367
+ --ef-color-focus-gap: #ffffff;
368
+ --ef-color-focus-ring: #000000;
369
+ --ef-color-surface-inverse: #000000;
370
+ --ef-color-surface-inverse-secondary: #303030;
371
+ --ef-color-surface-primary: #ffffff;
372
+ --ef-color-surface-secondary: #eeeeee;
373
+ --ef-color-text-heading: #000000;
374
+ --ef-color-text-inverse: #ffffff;
375
+ --ef-color-text-on-secondary-surface: #000000;
376
+ --ef-color-text-primary: #000000;
377
+ --ef-color-text-secondary: #303030;
378
+ }
379
+ [data-ef-theme="mono-semantic"] {
380
+ --ef-color-accent-primary: #3b5f55;
381
+ --ef-color-accent-secondary: #555555;
382
+ --ef-color-border-functional: #555555;
383
+ --ef-color-border-subtle: #d8d8d8;
384
+ --ef-color-control-active: #3b5f55;
385
+ --ef-color-control-thumb: #ffffff;
386
+ --ef-color-control-track: #555555;
387
+ --ef-color-focus-gap: #ffffff;
388
+ --ef-color-focus-ring: #161616;
389
+ --ef-color-surface-inverse: #161616;
390
+ --ef-color-surface-inverse-secondary: #303030;
391
+ --ef-color-surface-primary: #ffffff;
392
+ --ef-color-surface-secondary: #eeeeee;
393
+ --ef-color-text-heading: #161616;
394
+ --ef-color-text-inverse: #ffffff;
395
+ --ef-color-text-on-secondary-surface: #303030;
396
+ --ef-color-text-primary: #161616;
397
+ --ef-color-text-secondary: #555555;
398
+ }
399
+ [data-ef-theme="muted-professional"] {
400
+ --ef-color-accent-primary: #70405c;
401
+ --ef-color-accent-secondary: #356b64;
402
+ --ef-color-border-functional: #555555;
403
+ --ef-color-border-subtle: #d8d8d8;
404
+ --ef-color-control-active: #70405c;
405
+ --ef-color-control-thumb: #ffffff;
406
+ --ef-color-control-track: #555555;
407
+ --ef-color-focus-gap: #eeeeee;
408
+ --ef-color-focus-ring: #161616;
409
+ --ef-color-surface-inverse: #161616;
410
+ --ef-color-surface-inverse-secondary: #303030;
411
+ --ef-color-surface-primary: #eeeeee;
412
+ --ef-color-surface-secondary: #d8d8d8;
413
+ --ef-color-text-heading: #161616;
414
+ --ef-color-text-inverse: #ffffff;
415
+ --ef-color-text-on-secondary-surface: #303030;
416
+ --ef-color-text-primary: #161616;
417
+ --ef-color-text-secondary: #555555;
418
+ }
419
+ [data-ef-theme="nature-derived"] {
420
+ --ef-color-accent-primary: #315f3d;
421
+ --ef-color-accent-secondary: #315e75;
422
+ --ef-color-border-functional: #555555;
423
+ --ef-color-border-subtle: #dce2cf;
424
+ --ef-color-control-active: #315f3d;
425
+ --ef-color-control-thumb: #f1f0e5;
426
+ --ef-color-control-track: #555555;
427
+ --ef-color-focus-gap: #f1f0e5;
428
+ --ef-color-focus-ring: #20281f;
429
+ --ef-color-surface-inverse: #20281f;
430
+ --ef-color-surface-inverse-secondary: #303030;
431
+ --ef-color-surface-primary: #f1f0e5;
432
+ --ef-color-surface-secondary: #dce2cf;
433
+ --ef-color-text-heading: #20281f;
434
+ --ef-color-text-inverse: #f1f0e5;
435
+ --ef-color-text-on-secondary-surface: #20281f;
436
+ --ef-color-text-primary: #20281f;
437
+ --ef-color-text-secondary: #555555;
438
+ }
439
+ [data-ef-theme="neutral-editorial"] {
440
+ --ef-color-accent-primary: #905831;
441
+ --ef-color-accent-secondary: #356b64;
442
+ --ef-color-border-functional: #555555;
443
+ --ef-color-border-subtle: #e7e3da;
444
+ --ef-color-control-active: #905831;
445
+ --ef-color-control-thumb: #f6f4ef;
446
+ --ef-color-control-track: #555555;
447
+ --ef-color-focus-gap: #f6f4ef;
448
+ --ef-color-focus-ring: #161616;
449
+ --ef-color-surface-inverse: #161616;
450
+ --ef-color-surface-inverse-secondary: #303030;
451
+ --ef-color-surface-primary: #f6f4ef;
452
+ --ef-color-surface-secondary: #e7e3da;
453
+ --ef-color-text-heading: #161616;
454
+ --ef-color-text-inverse: #f6f4ef;
455
+ --ef-color-text-on-secondary-surface: #303030;
456
+ --ef-color-text-primary: #161616;
457
+ --ef-color-text-secondary: #555555;
458
+ }
459
+ [data-ef-theme="operations-salience"] {
460
+ --ef-color-accent-primary: #9c2f25;
461
+ --ef-color-accent-secondary: #315f8c;
462
+ --ef-color-border-functional: #555555;
463
+ --ef-color-border-subtle: #d8d8d8;
464
+ --ef-color-control-active: #9c2f25;
465
+ --ef-color-control-thumb: #ffffff;
466
+ --ef-color-control-track: #555555;
467
+ --ef-color-focus-gap: #ffffff;
468
+ --ef-color-focus-ring: #9c2f25;
469
+ --ef-color-surface-inverse: #161616;
470
+ --ef-color-surface-inverse-secondary: #303030;
471
+ --ef-color-surface-primary: #ffffff;
472
+ --ef-color-surface-secondary: #eeeeee;
473
+ --ef-color-text-heading: #161616;
474
+ --ef-color-text-inverse: #ffffff;
475
+ --ef-color-text-on-secondary-surface: #303030;
476
+ --ef-color-text-primary: #161616;
477
+ --ef-color-text-secondary: #555555;
478
+ }
479
+ [data-ef-theme="paper-ink"] {
480
+ --ef-color-accent-primary: #905831;
481
+ --ef-color-accent-secondary: #285c45;
482
+ --ef-color-border-functional: #555555;
483
+ --ef-color-border-subtle: #e7dece;
484
+ --ef-color-control-active: #905831;
485
+ --ef-color-control-thumb: #f7f2e7;
486
+ --ef-color-control-track: #555555;
487
+ --ef-color-focus-gap: #f7f2e7;
488
+ --ef-color-focus-ring: #211d18;
489
+ --ef-color-surface-inverse: #211d18;
490
+ --ef-color-surface-inverse-secondary: #303030;
491
+ --ef-color-surface-primary: #f7f2e7;
492
+ --ef-color-surface-secondary: #e7dece;
493
+ --ef-color-text-heading: #211d18;
494
+ --ef-color-text-inverse: #f7f2e7;
495
+ --ef-color-text-on-secondary-surface: #211d18;
496
+ --ef-color-text-primary: #211d18;
497
+ --ef-color-text-secondary: #555555;
498
+ }
499
+ [data-ef-theme="split-complementary"] {
500
+ --ef-color-accent-primary: #175f8f;
501
+ --ef-color-accent-secondary: #93451e;
502
+ --ef-color-border-functional: #555555;
503
+ --ef-color-border-subtle: #d8d8d8;
504
+ --ef-color-control-active: #175f8f;
505
+ --ef-color-control-thumb: #ffffff;
506
+ --ef-color-control-track: #555555;
507
+ --ef-color-focus-gap: #ffffff;
508
+ --ef-color-focus-ring: #7a3f70;
509
+ --ef-color-surface-inverse: #161616;
510
+ --ef-color-surface-inverse-secondary: #303030;
511
+ --ef-color-surface-primary: #ffffff;
512
+ --ef-color-surface-secondary: #eeeeee;
513
+ --ef-color-text-heading: #161616;
514
+ --ef-color-text-inverse: #ffffff;
515
+ --ef-color-text-on-secondary-surface: #303030;
516
+ --ef-color-text-primary: #161616;
517
+ --ef-color-text-secondary: #555555;
518
+ }
519
+ [data-ef-theme="warm-earth"] {
520
+ --ef-color-accent-primary: #905831;
521
+ --ef-color-accent-secondary: #356044;
522
+ --ef-color-border-functional: #555555;
523
+ --ef-color-border-subtle: #dfcfb8;
524
+ --ef-color-control-active: #905831;
525
+ --ef-color-control-thumb: #f3eadc;
526
+ --ef-color-control-track: #555555;
527
+ --ef-color-focus-gap: #f3eadc;
528
+ --ef-color-focus-ring: #29231c;
529
+ --ef-color-surface-inverse: #29231c;
530
+ --ef-color-surface-inverse-secondary: #303030;
531
+ --ef-color-surface-primary: #f3eadc;
532
+ --ef-color-surface-secondary: #dfcfb8;
533
+ --ef-color-text-heading: #29231c;
534
+ --ef-color-text-inverse: #f3eadc;
535
+ --ef-color-text-on-secondary-surface: #29231c;
536
+ --ef-color-text-primary: #29231c;
537
+ --ef-color-text-secondary: #555555;
538
+ }
539
+ }
540
+
541
+ /* --- source: src/marketing/roles.css --- */
542
+ /*
543
+ Forma marketing role contract: brand-neutral defaults.
544
+
545
+ Marketing foundations, components, and layouts consume only these role
546
+ tokens and Forma's core semantic tokens. A theme (for example the compiled
547
+ Echelon Marketing Theme) restates the roles at :root with higher
548
+ specificity, so these :where() defaults apply only when no theme does.
549
+
550
+ Defaults are declared on every theme/brand scope as well as :root so that
551
+ derived values recompute inside a nested data-ef-theme or data-ef-brand
552
+ subtree instead of inheriting the root's resolved value.
553
+ */
554
+ @layer echelon.tokens {
555
+ :where(:root, [data-ef-theme], [data-ef-brand]) {
556
+ /* Extended color roles, derived from core semantics. */
557
+ --ef-color-surface-elevated: var(--ef-color-surface-primary);
558
+ --ef-color-text-muted: var(--ef-color-text-secondary);
559
+ --ef-color-accent-hover: var(--ef-color-accent-primary);
560
+ /* Status defaults are deliberately hue-free: meaning is carried by text. */
561
+ --ef-color-status-success: var(--ef-color-text-primary);
562
+ --ef-color-status-warning: var(--ef-color-text-primary);
563
+ --ef-color-status-danger: var(--ef-color-text-primary);
564
+ --ef-color-status-info: var(--ef-color-text-primary);
565
+ }
566
+
567
+ :where(:root) {
568
+ /* Relational spacing scale (rem). Component gaps and padding use only
569
+ these steps; section and block rhythm use the fluid layout roles. */
570
+ --ef-space-1: var(--ef-primitive-space-1);
571
+ --ef-space-2: var(--ef-primitive-space-2);
572
+ --ef-space-3: var(--ef-primitive-space-3);
573
+ --ef-space-4: var(--ef-primitive-space-4);
574
+ --ef-space-5: var(--ef-primitive-space-5);
575
+ --ef-space-6: var(--ef-primitive-space-6);
576
+ --ef-space-7: var(--ef-primitive-space-7);
577
+ --ef-space-8: var(--ef-primitive-space-8);
578
+
579
+ --ef-type-family-body: var(--ef-primitive-font-family-sans);
580
+ --ef-type-family-display: var(--ef-primitive-font-family-display);
581
+ --ef-type-family-mono: var(--ef-primitive-font-family-mono);
582
+ --ef-type-size-label: var(--ef-primitive-font-size-xs);
583
+ --ef-type-size-small: var(--ef-primitive-font-size-sm);
584
+ --ef-type-size-body: var(--ef-primitive-font-size-md);
585
+ --ef-type-size-lead: var(--ef-primitive-font-size-fluid-lead);
586
+ --ef-type-size-h1: var(--ef-primitive-font-size-fluid-display-1);
587
+ --ef-type-size-h2: var(--ef-primitive-font-size-fluid-display-2);
588
+ --ef-type-size-h3: var(--ef-primitive-font-size-lg);
589
+ --ef-type-size-h4: var(--ef-primitive-font-size-md);
590
+ --ef-type-size-statement: var(--ef-primitive-font-size-fluid-display-3);
591
+ --ef-type-leading-body: var(--ef-primitive-line-height-normal);
592
+ --ef-type-leading-lead: var(--ef-primitive-line-height-normal);
593
+ --ef-type-leading-heading: var(--ef-primitive-line-height-snug);
594
+ --ef-type-leading-snug: var(--ef-primitive-line-height-snug);
595
+ --ef-type-weight-body: var(--ef-primitive-font-weight-regular);
596
+ --ef-type-weight-strong: var(--ef-primitive-font-weight-bold);
597
+ --ef-type-weight-heading: var(--ef-primitive-font-weight-semibold);
598
+ --ef-type-weight-label: var(--ef-primitive-font-weight-medium);
599
+ --ef-type-weight-nav: var(--ef-primitive-font-weight-semibold);
600
+ --ef-type-tracking-display: var(--ef-primitive-letter-spacing-normal);
601
+ --ef-type-tracking-label: var(--ef-primitive-letter-spacing-wide);
602
+ --ef-type-tracking-body: var(--ef-primitive-letter-spacing-normal);
603
+
604
+ --ef-layout-measure: var(--ef-primitive-size-measure);
605
+ --ef-layout-measure-narrow: var(--ef-primitive-size-measure-narrow);
606
+ --ef-layout-width-narrow: var(--ef-primitive-size-container-narrow);
607
+ --ef-layout-width-standard: var(--ef-primitive-size-container-standard);
608
+ --ef-layout-width-wide: var(--ef-primitive-size-container-wide);
609
+ --ef-layout-width-max: var(--ef-primitive-size-container-max);
610
+ --ef-layout-gutter: var(--ef-primitive-size-fluid-gutter);
611
+ --ef-layout-section-space: var(--ef-primitive-size-fluid-section-space);
612
+ --ef-layout-block-space: var(--ef-primitive-size-fluid-block-space);
613
+ --ef-layout-grid-gap: var(--ef-primitive-space-6);
614
+ --ef-layout-stack-space: var(--ef-primitive-space-6);
615
+ --ef-layout-target-min: var(--ef-primitive-size-target-min);
616
+ /* Clearance kept below a sticky header for anchors and sticky rails. */
617
+ --ef-layout-header-offset: 6rem;
618
+ /* Card and fact minimums decide when grids drop a column (content-driven). */
619
+ --ef-layout-card-min: 15rem;
620
+ --ef-layout-fact-min: 11rem;
621
+
622
+ --ef-shape-radius: var(--ef-primitive-radius-small);
623
+ --ef-shape-border-width: var(--ef-primitive-border-width-thin);
624
+ --ef-shape-border-width-accent: var(--ef-primitive-border-width-accent);
625
+
626
+ --ef-effect-shadow-raised: var(--ef-primitive-shadow-raised);
627
+ /* Marketing state changes are perceptual interpolation (non-spatial).
628
+ The fallbacks restate Forma's shared perceptual vocabulary for pages
629
+ that load the marketing bundle without components.css. */
630
+ --ef-effect-transition-duration: var(--ef-motion-perceptual-duration, 120ms);
631
+ --ef-effect-transition-easing: var(--ef-motion-perceptual-easing, cubic-bezier(0.2, 0, 0, 1));
632
+
633
+ --ef-focus-ring-width: var(--ef-primitive-focus-ring-width);
634
+ --ef-focus-ring-offset: var(--ef-primitive-focus-ring-offset);
635
+ --ef-focus-halo-width: var(--ef-primitive-focus-halo-width);
636
+ }
637
+ }
638
+
639
+ /* --- source: dist/foundations.css --- */
640
+ @layer echelon.foundations {
641
+ *, *::before, *::after { box-sizing: border-box; }
642
+
643
+ :where(html) {
644
+ color-scheme: light dark;
645
+ -webkit-text-size-adjust: 100%;
646
+ text-size-adjust: 100%;
647
+ font-family: var(--ef-primitive-font-family-sans, system-ui, sans-serif);
648
+ background: var(--ef-color-surface-primary, #f2efe7);
649
+ color: var(--ef-color-text-primary, #171a18);
650
+ }
651
+
652
+ :where(body) {
653
+ margin: 0;
654
+ background: var(--ef-color-surface-primary, #f2efe7);
655
+ color: var(--ef-color-text-primary, #171a18);
656
+ font-family: var(--ef-primitive-font-family-sans, system-ui, sans-serif);
657
+ font-size: 1rem;
658
+ line-height: 1.6;
659
+ }
660
+
661
+ :where(h1, h2) {
662
+ color: var(--ef-color-text-heading, #202421);
663
+ font-family: var(--ef-primitive-font-family-display, Georgia, serif);
664
+ font-weight: 500;
665
+ letter-spacing: -0.03em;
666
+ line-height: 1.02;
667
+ }
668
+
669
+ :where(h3, h4, h5, h6) {
670
+ color: var(--ef-color-text-heading, #202421);
671
+ line-height: 1.25;
672
+ }
673
+
674
+ :where(p) {
675
+ color: var(--ef-color-text-secondary, #686d68);
676
+ max-inline-size: 72ch;
677
+ }
678
+
679
+ :where(a) {
680
+ color: var(--ef-color-accent-primary, #905831);
681
+ text-decoration-thickness: 0.08em;
682
+ text-underline-offset: 0.18em;
683
+ }
684
+
685
+ :where(button, input, select, textarea) {
686
+ max-inline-size: 100%;
687
+ font: inherit;
688
+ }
689
+
690
+ :where(img, picture, video, canvas, svg) {
691
+ max-inline-size: 100%;
692
+ }
693
+
694
+ :where(img, video, canvas) {
695
+ block-size: auto;
696
+ }
697
+
698
+ :where(button, .ef-button) {
699
+ min-block-size: 2.75rem;
700
+ padding: 0.65rem 1rem;
701
+ border: 1px solid var(--ef-color-border-functional, #3a403c);
702
+ border-radius: var(--ef-primitive-radius-none, 0);
703
+ background: var(--ef-color-surface-primary, #f2efe7);
704
+ color: var(--ef-color-text-primary, #171a18);
705
+ font-weight: 700;
706
+ /*
707
+ * Hover and press feedback is perceptual interpolation (MOT-014, MOT-026):
708
+ * it changes the surface, never the hit target's position or size. The
709
+ * fallbacks restate the shared vocabulary for pages that load
710
+ * foundations.css without components.css.
711
+ */
712
+ transition:
713
+ background-color var(--ef-motion-perceptual-duration, 120ms) var(--ef-motion-perceptual-easing, cubic-bezier(0.2, 0, 0, 1)),
714
+ border-color var(--ef-motion-perceptual-duration, 120ms) var(--ef-motion-perceptual-easing, cubic-bezier(0.2, 0, 0, 1));
715
+ }
716
+
717
+ :where(button, .ef-button):where(:not(:disabled)):hover {
718
+ background: var(--ef-color-surface-secondary, #e3e0d7);
719
+ }
720
+
721
+ /*
722
+ * Press onset is a direct projection of pointer/key down: it begins
723
+ * immediately and never delays activation. Release returns through the
724
+ * perceptual interpolation above.
725
+ */
726
+ :where(button, .ef-button):where(:not(:disabled)):active {
727
+ background: color-mix(in srgb, var(--ef-color-surface-secondary, #e3e0d7) 82%, var(--ef-color-text-primary, #171a18));
728
+ transition-duration: var(--ef-motion-direct-duration, 0ms);
729
+ }
730
+
731
+ :where(input:not([type="checkbox"], [type="radio"], [type="range"]), textarea, select) {
732
+ min-block-size: 2.75rem;
733
+ inline-size: 100%;
734
+ padding: 0.7rem 0.8rem;
735
+ border: 1px solid var(--ef-color-border-functional, #3a403c);
736
+ border-radius: var(--ef-primitive-radius-none, 0);
737
+ background: var(--ef-color-surface-primary, #f2efe7);
738
+ color: var(--ef-color-text-primary, #171a18);
739
+ }
740
+
741
+ :where(:focus-visible) {
742
+ outline: 3px solid var(--ef-color-focus-gap, #f2efe7);
743
+ outline-offset: 2px;
744
+ box-shadow: 0 0 0 5px var(--ef-color-focus-ring, #171a18);
745
+ }
746
+
747
+ .ef-stack { display: flex; flex-direction: column; gap: var(--ef-stack-gap, var(--ef-primitive-spacing-4, 1rem)); }
748
+ .ef-cluster { display: flex; flex-wrap: wrap; gap: var(--ef-cluster-gap, var(--ef-primitive-spacing-3, 0.75rem)); align-items: center; }
749
+ .ef-grid { display: grid; gap: var(--ef-grid-gap, var(--ef-primitive-spacing-4, 1rem)); grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--ef-grid-min, 16rem)), 1fr)); }
750
+ .ef-section { padding-block: var(--ef-section-space, var(--ef-primitive-spacing-7, 3rem)); }
751
+ .ef-surface { min-inline-size: 0; padding: var(--ef-surface-space, var(--ef-primitive-spacing-5, 1.5rem)); background: var(--ef-color-surface-secondary, #e3e0d7); color: var(--ef-color-text-on-secondary-surface, #3a403c); border: 1px solid var(--ef-color-border-subtle, #e3e0d7); }
752
+ .ef-surface :where(h1, h2, h3, h4, h5, h6, p) { color: inherit; }
753
+
754
+ :where(h1, h2, h3, h4, h5, h6, p, a, label, legend, td, th) {
755
+ overflow-wrap: anywhere;
756
+ }
757
+
758
+ @media (prefers-reduced-motion: reduce) {
759
+ *, *::before, *::after {
760
+ scroll-behavior: auto !important;
761
+ animation-duration: 0.01ms !important;
762
+ animation-iteration-count: 1 !important;
763
+ transition-duration: 0.01ms !important;
764
+ }
765
+ }
766
+
767
+ @media (forced-colors: active) {
768
+ /*
769
+ * Forced-colors token projection (FORMA-A11Y-001). Every semantic color
770
+ * token resolves to a system color, so author colors agree with what the
771
+ * user agent forces: foreground roles become CanvasText and surfaces
772
+ * become Canvas, for every theme, brand and skin scope. Without this,
773
+ * theme text colors survive where engines do not force them (for example
774
+ * -webkit-text-fill-color, which resolves currentcolor before forcing, and
775
+ * engines that only emulate the media query), producing light theme text
776
+ * on a forced Canvas. !important in this early layer outranks later theme
777
+ * and brand layers: the user's forced-colors choice wins. Selection and
778
+ * state rules that need Highlight keep their explicit forced-colors rules.
779
+ */
780
+ :root, [data-ef-theme], [data-ef-brand], [data-ef-skin] {
781
+ --ef-color-text-primary: CanvasText !important;
782
+ --ef-color-text-heading: CanvasText !important;
783
+ --ef-color-text-secondary: CanvasText !important;
784
+ --ef-color-text-muted: CanvasText !important;
785
+ --ef-color-text-on-secondary-surface: CanvasText !important;
786
+ --ef-color-text-inverse: CanvasText !important;
787
+ --ef-color-accent-primary: CanvasText !important;
788
+ --ef-color-accent-secondary: CanvasText !important;
789
+ --ef-color-accent-hover: CanvasText !important;
790
+ --ef-color-border-functional: CanvasText !important;
791
+ --ef-color-border-subtle: CanvasText !important;
792
+ --ef-color-status-danger: CanvasText !important;
793
+ --ef-color-status-warning: CanvasText !important;
794
+ --ef-color-status-success: CanvasText !important;
795
+ --ef-color-status-info: CanvasText !important;
796
+ --ef-color-control-active: CanvasText !important;
797
+ --ef-color-control-thumb: Canvas !important;
798
+ --ef-color-control-track: CanvasText !important;
799
+ --ef-color-focus-ring: CanvasText !important;
800
+ --ef-color-focus-gap: Canvas !important;
801
+ --ef-color-surface-primary: Canvas !important;
802
+ --ef-color-surface-secondary: Canvas !important;
803
+ --ef-color-surface-elevated: Canvas !important;
804
+ --ef-color-surface-inverse: Canvas !important;
805
+ --ef-color-surface-inverse-secondary: Canvas !important;
806
+ color: CanvasText;
807
+ background-color: Canvas;
808
+ }
809
+
810
+ :where(button, .ef-button, input, textarea, select, .ef-surface) {
811
+ border-color: CanvasText;
812
+ }
813
+ }
814
+
815
+ /* Visual Engineering composition primitives -------------------------- */
816
+ .ef-breakout { inline-size: min(100%, var(--ef-breakout-max, 90rem)); max-inline-size: none; }
817
+ .ef-rail { --ef-rail-measure: minmax(12rem, 18rem); --ef-rail-content-min: 50%; --ef-rail-space: var(--ef-primitive-spacing-5, 1.5rem); display: grid; grid-template-columns: var(--ef-rail-measure) minmax(var(--ef-rail-content-min), 1fr); gap: var(--ef-rail-space); align-items: start; }
818
+ .ef-rail[data-side="end"] { grid-template-columns: minmax(var(--ef-rail-content-min), 1fr) var(--ef-rail-measure); }
819
+ .ef-rail > * { min-inline-size: 0; }
820
+ .ef-responsive-grid { --ef-responsive-grid-min: 16rem; --ef-responsive-grid-space: var(--ef-primitive-spacing-4, 1rem); display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--ef-responsive-grid-min)), 1fr)); gap: var(--ef-responsive-grid-space); }
821
+ .ef-responsive-grid > * { min-inline-size: 0; }
822
+ .ef-span-2 { grid-column: span 2; }
823
+ .ef-span-full { grid-column: 1 / -1; }
824
+ .ef-bounded-overflow { max-inline-size: 100%; overflow: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }
825
+ .ef-priority-stack { --ef-priority-min: 18rem; --ef-priority-space: var(--ef-primitive-spacing-4, 1rem); display: flex; flex-wrap: wrap; gap: var(--ef-priority-space); align-items: start; }
826
+ .ef-priority-stack > * { flex: 1 1 var(--ef-priority-min); min-inline-size: min(100%, var(--ef-priority-min)); }
827
+ .ef-priority-stack > [data-priority="primary"] { flex-grow: 2; }
828
+ .ef-focus-stage { --ef-focus-stage-support: minmax(14rem, 20rem); --ef-focus-stage-space: var(--ef-primitive-spacing-5, 1.5rem); display: grid; grid-template-columns: minmax(0, 1fr) var(--ef-focus-stage-support); gap: var(--ef-focus-stage-space); align-items: start; }
829
+ .ef-focus-stage__primary, .ef-focus-stage__support { min-inline-size: 0; }
830
+ .ef-mosaic { --ef-mosaic-space: var(--ef-primitive-spacing-4, 1rem); display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--ef-mosaic-space); }
831
+ .ef-mosaic > * { min-inline-size: 0; }
832
+ .ef-mosaic > [data-span="2"] { grid-column: span 2; }
833
+ .ef-mosaic > [data-span="full"] { grid-column: 1 / -1; }
834
+ .ef-dense-ledger { inline-size: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
835
+ .ef-dense-ledger :is(th, td) { padding: var(--ef-ledger-cell-space, var(--ef-primitive-spacing-2, 0.5rem)); border-block-end: 1px solid var(--ef-color-border-subtle, #e3e0d7); text-align: start; vertical-align: top; }
836
+ [data-density="relaxed"] { --ef-density-space: var(--ef-primitive-spacing-5, 1.5rem); }
837
+ [data-density="standard"] { --ef-density-space: var(--ef-primitive-spacing-4, 1rem); }
838
+ [data-density="compact"], [data-density="analytical"] { --ef-density-space: var(--ef-primitive-spacing-2, 0.5rem); }
839
+ :where(.ef-stack, .ef-grid, .ef-responsive-grid, .ef-priority-stack)[data-density] { gap: var(--ef-density-space); }
840
+ @media (max-width: 48rem) { .ef-rail, .ef-rail[data-side="end"], .ef-focus-stage { grid-template-columns: minmax(0, 1fr); } .ef-mosaic { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ef-span-2 { grid-column: 1 / -1; } }
841
+ @media (max-width: 30rem) { .ef-mosaic { grid-template-columns: minmax(0, 1fr); } .ef-mosaic > [data-span="2"], .ef-mosaic > [data-span="full"] { grid-column: auto; } .ef-responsive-grid { --ef-responsive-grid-min: 100%; } .ef-priority-stack { --ef-priority-min: 100%; } }
842
+ }
843
+
844
+ /* --- source: src/marketing/foundations.css --- */
845
+ /*
846
+ Forma marketing foundations.
847
+
848
+ Everything here is scoped to the MarketingShell root (.ef-site) so that
849
+ loading the marketing layer never restyles an application that also uses
850
+ Forma. Values come only from role tokens (src/marketing/roles.css) and core
851
+ semantic tokens; no brand values live in this file.
852
+
853
+ Surface tones: every region that changes background declares a tone with
854
+ data-ef-tone. A tone sets a small, contrast-safe set of context variables
855
+ (--ef-tone-*) that components read, so text, links, labels, and rules stay
856
+ legible on every surface without per-component color overrides.
857
+ */
858
+ @layer echelon.marketing.foundations {
859
+ :where(:root, [data-ef-theme], [data-ef-brand]),
860
+ .ef-site,
861
+ [data-ef-tone="page"] {
862
+ --ef-tone-background: var(--ef-color-surface-primary);
863
+ --ef-tone-text: var(--ef-color-text-primary);
864
+ --ef-tone-heading: var(--ef-color-text-heading);
865
+ --ef-tone-muted: var(--ef-color-text-muted);
866
+ --ef-tone-label: var(--ef-color-accent-secondary);
867
+ --ef-tone-link: var(--ef-color-accent-primary);
868
+ --ef-tone-link-hover: var(--ef-color-accent-hover);
869
+ --ef-tone-rule: var(--ef-color-border-subtle);
870
+ --ef-tone-rule-strong: var(--ef-color-border-functional);
871
+ --ef-tone-action-background: var(--ef-color-surface-inverse);
872
+ --ef-tone-action-text: var(--ef-color-text-inverse);
873
+ --ef-tone-action-hover: var(--ef-color-surface-inverse-secondary);
874
+ --ef-tone-hover: var(--ef-color-surface-secondary);
875
+ }
876
+
877
+ /* Accent colors are not validated against the secondary surface, so links
878
+ and labels on it fall back to text roles that are. Cards default to
879
+ this tone. */
880
+ [data-ef-tone="surface"],
881
+ :where(.ef-card:not([data-ef-tone])) {
882
+ --ef-tone-background: var(--ef-color-surface-secondary);
883
+ --ef-tone-text: var(--ef-color-text-primary);
884
+ --ef-tone-heading: var(--ef-color-text-heading);
885
+ --ef-tone-muted: var(--ef-color-text-on-secondary-surface);
886
+ --ef-tone-label: var(--ef-color-text-on-secondary-surface);
887
+ --ef-tone-link: var(--ef-color-text-primary);
888
+ --ef-tone-link-hover: var(--ef-color-text-primary);
889
+ --ef-tone-rule: var(--ef-color-border-subtle);
890
+ --ef-tone-rule-strong: var(--ef-color-border-functional);
891
+ --ef-tone-hover: var(--ef-color-surface-primary);
892
+ }
893
+
894
+ [data-ef-tone="elevated"] {
895
+ --ef-tone-background: var(--ef-color-surface-elevated);
896
+ --ef-tone-text: var(--ef-color-text-primary);
897
+ --ef-tone-heading: var(--ef-color-text-heading);
898
+ --ef-tone-muted: var(--ef-color-text-primary);
899
+ --ef-tone-label: var(--ef-color-text-primary);
900
+ --ef-tone-link: var(--ef-color-text-primary);
901
+ --ef-tone-link-hover: var(--ef-color-text-primary);
902
+ --ef-tone-rule: var(--ef-color-border-subtle);
903
+ --ef-tone-rule-strong: var(--ef-color-border-functional);
904
+ --ef-tone-hover: var(--ef-color-surface-primary);
905
+ }
906
+
907
+ [data-ef-tone="inverse"] {
908
+ --ef-tone-background: var(--ef-color-surface-inverse);
909
+ --ef-tone-text: var(--ef-color-text-inverse);
910
+ --ef-tone-heading: var(--ef-color-text-inverse);
911
+ --ef-tone-muted: var(--ef-color-text-inverse);
912
+ --ef-tone-label: var(--ef-color-text-inverse);
913
+ --ef-tone-link: var(--ef-color-text-inverse);
914
+ --ef-tone-link-hover: var(--ef-color-text-inverse);
915
+ --ef-tone-rule: var(--ef-color-surface-inverse-secondary);
916
+ --ef-tone-rule-strong: var(--ef-color-text-inverse);
917
+ --ef-tone-action-background: var(--ef-color-surface-primary);
918
+ --ef-tone-action-text: var(--ef-color-text-primary);
919
+ --ef-tone-action-hover: var(--ef-color-surface-secondary);
920
+ --ef-tone-hover: var(--ef-color-surface-inverse-secondary);
921
+ }
922
+
923
+ [data-ef-tone],
924
+ :where(.ef-card:not([data-ef-tone])) {
925
+ background: var(--ef-tone-background);
926
+ color: var(--ef-tone-text);
927
+ }
928
+
929
+ :where(html):has(> body.ef-site) {
930
+ background: var(--ef-color-surface-primary);
931
+ }
932
+
933
+ .ef-site {
934
+ /* Stacking context keeps an optional theme backdrop behind content even
935
+ when the shell is not the body element. */
936
+ isolation: isolate;
937
+ display: flex;
938
+ flex-direction: column;
939
+ margin: 0;
940
+ background: var(--ef-color-surface-primary);
941
+ color: var(--ef-tone-text);
942
+ font-family: var(--ef-type-family-body);
943
+ font-size: var(--ef-type-size-body);
944
+ font-weight: var(--ef-type-weight-body);
945
+ letter-spacing: var(--ef-type-tracking-body);
946
+ line-height: var(--ef-type-leading-body);
947
+ text-rendering: optimizeLegibility;
948
+ }
949
+
950
+ /* The shell fills the viewport only when it is the document body. */
951
+ body.ef-site {
952
+ min-block-size: 100vh;
953
+ min-block-size: 100dvh;
954
+ }
955
+
956
+ /* Optional brand backdrop supplied by a theme; absent means none. */
957
+ .ef-site::before {
958
+ content: "";
959
+ position: fixed;
960
+ inset: 0;
961
+ z-index: -1;
962
+ pointer-events: none;
963
+ background-image: var(--ef-site-backdrop, none);
964
+ background-size: var(--ef-site-backdrop-size, auto);
965
+ opacity: var(--ef-site-backdrop-opacity, 1);
966
+ }
967
+
968
+ .ef-site :where(h1, h2, h3, h4, h5, h6) {
969
+ margin-block: 0;
970
+ color: var(--ef-tone-heading);
971
+ text-wrap: balance;
972
+ }
973
+
974
+ .ef-site :where(h1, h2) {
975
+ font-family: var(--ef-type-family-display);
976
+ font-weight: var(--ef-type-weight-heading);
977
+ letter-spacing: var(--ef-type-tracking-display);
978
+ line-height: var(--ef-type-leading-heading);
979
+ }
980
+
981
+ .ef-site :where(h1) { font-size: var(--ef-type-size-h1); max-inline-size: 14ch; }
982
+ .ef-site :where(h2) { font-size: var(--ef-type-size-h2); max-inline-size: 18ch; }
983
+ .ef-site :where(h3) { font-size: var(--ef-type-size-h3); line-height: var(--ef-type-leading-snug); }
984
+ .ef-site :where(h4, h5, h6) { font-size: var(--ef-type-size-h4); line-height: var(--ef-type-leading-snug); }
985
+
986
+ .ef-site :where(p) {
987
+ margin-block: 0 var(--ef-space-4);
988
+ max-inline-size: var(--ef-layout-measure);
989
+ color: var(--ef-tone-muted);
990
+ }
991
+
992
+ .ef-site :where(p:last-child) { margin-block-end: 0; }
993
+
994
+ /* Links stay underlined everywhere except where a component gives them
995
+ another non-color cue (navigation, buttons, cards). */
996
+ .ef-site :where(a) {
997
+ color: var(--ef-tone-link);
998
+ text-decoration-line: underline;
999
+ text-decoration-thickness: var(--ef-shape-border-width);
1000
+ text-underline-offset: 0.2em;
1001
+ }
1002
+
1003
+ .ef-site :where(a:hover) {
1004
+ color: var(--ef-tone-link-hover);
1005
+ text-decoration-thickness: calc(var(--ef-shape-border-width) * 2);
1006
+ }
1007
+
1008
+ .ef-site :where(ul, ol) { margin-block: 0 var(--ef-space-4); padding-inline-start: var(--ef-space-5); }
1009
+ .ef-site :where(li + li) { margin-block-start: 0.45em; }
1010
+ /* Only prose lists take the reading measure; classed lists are structure. */
1011
+ .ef-site :where(ul:not([class]), ol:not([class])) > li { max-inline-size: var(--ef-layout-measure); }
1012
+ .ef-site :where(strong, b) { font-weight: var(--ef-type-weight-strong); }
1013
+ .ef-site :where(img, svg, video, canvas, picture) { max-inline-size: 100%; block-size: auto; }
1014
+ .ef-site :where(code, kbd, samp, pre) { font-family: var(--ef-type-family-mono); font-size: 0.9em; }
1015
+
1016
+ .ef-site :where(:not(pre) > code) {
1017
+ padding: 0.1em 0.3em;
1018
+ background: var(--ef-tone-hover);
1019
+ color: var(--ef-tone-text);
1020
+ overflow-wrap: anywhere;
1021
+ }
1022
+
1023
+ .ef-site :where(hr) {
1024
+ margin-block: var(--ef-layout-section-space);
1025
+ border: 0;
1026
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1027
+ }
1028
+
1029
+ .ef-site :where(blockquote) {
1030
+ margin: var(--ef-layout-block-space) 0;
1031
+ padding-inline-start: var(--ef-layout-block-space);
1032
+ border-inline-start: var(--ef-shape-border-width-accent) solid var(--ef-color-accent-primary);
1033
+ font-family: var(--ef-type-family-display);
1034
+ font-size: var(--ef-type-size-lead);
1035
+ line-height: var(--ef-type-leading-lead);
1036
+ }
1037
+
1038
+ .ef-site :where(blockquote p) { color: var(--ef-tone-text); }
1039
+
1040
+ /* One focus treatment for the whole shell: a gap-colored outline inside a
1041
+ ring-colored halo remains visible on every tone. */
1042
+ .ef-site :where(:focus-visible) {
1043
+ outline: var(--ef-focus-ring-width) solid var(--ef-color-focus-gap);
1044
+ outline-offset: var(--ef-focus-ring-offset);
1045
+ box-shadow: 0 0 0 var(--ef-focus-halo-width) var(--ef-color-focus-ring);
1046
+ }
1047
+
1048
+ @media (prefers-reduced-motion: no-preference) {
1049
+ :where(html):has(.ef-site) { scroll-behavior: smooth; }
1050
+ }
1051
+
1052
+ /* Anchored targets must land below a sticky header (see layouts.css). */
1053
+ @media (min-width: 40rem) and (min-height: 36rem) {
1054
+ :where(html):has(.ef-site-header) { scroll-padding-block-start: var(--ef-layout-header-offset); }
1055
+ }
1056
+ }
1057
+
1058
+ /* --- source: src/marketing/components.css --- */
1059
+ /*
1060
+ Forma marketing components.
1061
+
1062
+ Small, composable presentation primitives for public/marketing pages. Each
1063
+ component reads role tokens and the surrounding surface tone (--ef-tone-*);
1064
+ none embeds a brand value, a product name, or page-specific placement.
1065
+ Components own their intrinsic layout only. Where they sit on a page is
1066
+ owned by layouts.css or the consuming page composition.
1067
+
1068
+ Responsive behavior is content-driven: wrapping flex rows and auto-fit grids
1069
+ with minimum sizes. The two container queries below exist because a row's
1070
+ column structure cannot be expressed as a minimum item size.
1071
+ */
1072
+ @layer echelon.marketing.components {
1073
+ /* Skip link --------------------------------------------------------- */
1074
+ .ef-skip-link {
1075
+ position: fixed;
1076
+ inset-block-start: var(--ef-space-2);
1077
+ inset-inline-start: var(--ef-space-2);
1078
+ z-index: 100;
1079
+ display: inline-flex;
1080
+ align-items: center;
1081
+ min-block-size: var(--ef-layout-target-min);
1082
+ padding-inline: var(--ef-space-4);
1083
+ background: var(--ef-color-surface-primary);
1084
+ color: var(--ef-color-text-primary);
1085
+ font-weight: var(--ef-type-weight-strong);
1086
+ transform: translateY(-200%);
1087
+ }
1088
+
1089
+ .ef-skip-link:focus,
1090
+ .ef-skip-link:focus-visible {
1091
+ transform: none;
1092
+ }
1093
+
1094
+ /* Site header and navigation ---------------------------------------- */
1095
+ .ef-site-header {
1096
+ container: ef-site-header / inline-size;
1097
+ position: relative;
1098
+ z-index: 20;
1099
+ border-block-end: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1100
+ background: color-mix(in srgb, var(--ef-color-surface-primary) 94%, transparent);
1101
+ -webkit-backdrop-filter: blur(14px);
1102
+ backdrop-filter: blur(14px);
1103
+ }
1104
+
1105
+ .ef-site-header__inner {
1106
+ display: flex;
1107
+ flex-wrap: wrap;
1108
+ align-items: center;
1109
+ justify-content: space-between;
1110
+ gap: var(--ef-space-2) var(--ef-space-7);
1111
+ inline-size: min(100%, var(--ef-layout-width-max));
1112
+ margin-inline: auto;
1113
+ padding: var(--ef-space-3) var(--ef-layout-gutter);
1114
+ }
1115
+
1116
+ .ef-site-header__identity {
1117
+ display: flex;
1118
+ flex-wrap: wrap;
1119
+ align-items: center;
1120
+ gap: var(--ef-space-1) var(--ef-space-3);
1121
+ min-inline-size: 0;
1122
+ }
1123
+
1124
+ .ef-site-header__brand {
1125
+ display: inline-flex;
1126
+ align-items: center;
1127
+ gap: var(--ef-space-3);
1128
+ min-block-size: var(--ef-layout-target-min);
1129
+ color: var(--ef-tone-text);
1130
+ font-weight: var(--ef-type-weight-strong);
1131
+ text-decoration: none;
1132
+ }
1133
+
1134
+ .ef-site-header__brand:hover { color: var(--ef-tone-text); text-decoration: underline; }
1135
+
1136
+ /* The brand name stays visible at every width; it wraps rather than hides,
1137
+ because the mark alone is decorative (aria-hidden). */
1138
+ .ef-site-header__name { min-inline-size: 0; overflow-wrap: anywhere; }
1139
+
1140
+ .ef-site-header__mark {
1141
+ display: grid;
1142
+ place-items: center;
1143
+ flex: none;
1144
+ inline-size: 2.35rem;
1145
+ aspect-ratio: 1;
1146
+ border-radius: var(--ef-shape-radius);
1147
+ background: var(--ef-color-surface-inverse);
1148
+ color: var(--ef-color-text-inverse);
1149
+ font-family: var(--ef-type-family-mono);
1150
+ font-size: var(--ef-type-size-label);
1151
+ }
1152
+
1153
+ .ef-site-header__tagline {
1154
+ margin: 0;
1155
+ max-inline-size: 24ch;
1156
+ color: var(--ef-tone-muted);
1157
+ font-family: var(--ef-type-family-mono);
1158
+ font-size: var(--ef-type-size-label);
1159
+ line-height: var(--ef-type-leading-snug);
1160
+ }
1161
+
1162
+ /* The tagline repeats identity context; below this width it would push the
1163
+ navigation onto a third line, so it yields. The brand name never hides. */
1164
+ @container ef-site-header (inline-size < 56rem) {
1165
+ .ef-site-header__tagline { display: none; }
1166
+ }
1167
+
1168
+ .ef-site-nav__list {
1169
+ display: flex;
1170
+ flex-wrap: wrap;
1171
+ justify-content: flex-end;
1172
+ gap: var(--ef-space-1);
1173
+ margin: 0;
1174
+ padding: 0;
1175
+ list-style: none;
1176
+ }
1177
+
1178
+ .ef-site-nav__list > li { margin: 0; }
1179
+
1180
+ .ef-site-nav__link {
1181
+ display: inline-flex;
1182
+ align-items: center;
1183
+ min-block-size: var(--ef-layout-target-min);
1184
+ padding-inline: var(--ef-space-3);
1185
+ border-block-end: calc(var(--ef-shape-border-width) * 2) solid transparent;
1186
+ color: var(--ef-tone-text);
1187
+ font-size: var(--ef-type-size-small);
1188
+ font-weight: var(--ef-type-weight-nav);
1189
+ text-decoration: none;
1190
+ }
1191
+
1192
+ .ef-site-nav__link:hover {
1193
+ color: var(--ef-tone-text);
1194
+ border-block-end-color: var(--ef-color-accent-primary);
1195
+ }
1196
+
1197
+ /* Current location uses a persistent rule plus aria-current, not hue alone. */
1198
+ .ef-site-nav__link[aria-current="page"],
1199
+ .ef-site-nav__link[aria-current="true"] {
1200
+ border-block-end-color: var(--ef-tone-rule-strong);
1201
+ }
1202
+
1203
+ .ef-site-nav__link[data-ef-variant="action"] {
1204
+ margin-inline-start: var(--ef-space-2);
1205
+ border-radius: var(--ef-shape-radius);
1206
+ background: var(--ef-tone-action-background);
1207
+ color: var(--ef-tone-action-text);
1208
+ }
1209
+
1210
+ .ef-site-nav__link[data-ef-variant="action"]:hover {
1211
+ background: var(--ef-tone-action-hover);
1212
+ color: var(--ef-tone-action-text);
1213
+ border-block-end-color: var(--ef-tone-action-text);
1214
+ }
1215
+
1216
+ /* Text roles --------------------------------------------------------- */
1217
+ .ef-eyebrow {
1218
+ margin-block: 0 var(--ef-space-3);
1219
+ color: var(--ef-tone-label);
1220
+ font-family: var(--ef-type-family-mono);
1221
+ font-size: var(--ef-type-size-label);
1222
+ font-weight: var(--ef-type-weight-label);
1223
+ letter-spacing: var(--ef-type-tracking-label);
1224
+ line-height: var(--ef-type-leading-snug);
1225
+ text-transform: uppercase;
1226
+ }
1227
+
1228
+ .ef-lead {
1229
+ max-inline-size: var(--ef-layout-measure-narrow);
1230
+ color: var(--ef-tone-text);
1231
+ font-size: var(--ef-type-size-lead);
1232
+ line-height: var(--ef-type-leading-lead);
1233
+ }
1234
+
1235
+ .ef-statement {
1236
+ margin: 0;
1237
+ padding: var(--ef-space-5) 0 0;
1238
+ border-inline-start: 0;
1239
+ border-block-start: var(--ef-shape-border-width-accent) solid var(--ef-color-accent-primary);
1240
+ color: var(--ef-tone-text);
1241
+ font-family: var(--ef-type-family-display);
1242
+ font-size: var(--ef-type-size-statement);
1243
+ line-height: var(--ef-type-leading-snug);
1244
+ }
1245
+
1246
+ .ef-statement :where(p) { color: inherit; max-inline-size: none; }
1247
+
1248
+ /* Actions and buttons ------------------------------------------------ */
1249
+ .ef-actions {
1250
+ display: flex;
1251
+ flex-wrap: wrap;
1252
+ align-items: center;
1253
+ gap: var(--ef-space-3);
1254
+ }
1255
+
1256
+ .ef-site .ef-button {
1257
+ display: inline-flex;
1258
+ align-items: center;
1259
+ justify-content: center;
1260
+ gap: var(--ef-space-3);
1261
+ min-block-size: calc(var(--ef-layout-target-min) + var(--ef-space-2));
1262
+ padding: var(--ef-space-3) var(--ef-space-5);
1263
+ border: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1264
+ border-radius: var(--ef-shape-radius);
1265
+ background: transparent;
1266
+ color: var(--ef-tone-text);
1267
+ font: inherit;
1268
+ font-size: var(--ef-type-size-small);
1269
+ font-weight: var(--ef-type-weight-strong);
1270
+ line-height: var(--ef-type-leading-snug);
1271
+ text-align: center;
1272
+ text-decoration: none;
1273
+ cursor: pointer;
1274
+ /* Hover and press are perceptual emphasis on the surface only: the hit
1275
+ target never moves under the pointer (MOT-014). */
1276
+ transition:
1277
+ background-color var(--ef-effect-transition-duration) var(--ef-effect-transition-easing),
1278
+ color var(--ef-effect-transition-duration) var(--ef-effect-transition-easing);
1279
+ }
1280
+
1281
+ .ef-site .ef-button:hover { background: var(--ef-tone-hover); color: var(--ef-tone-text); }
1282
+
1283
+ .ef-site .ef-button[data-ef-variant="primary"] {
1284
+ border-color: var(--ef-tone-action-background);
1285
+ background: var(--ef-tone-action-background);
1286
+ color: var(--ef-tone-action-text);
1287
+ }
1288
+
1289
+ .ef-site .ef-button[data-ef-variant="primary"]:hover {
1290
+ background: var(--ef-tone-action-hover);
1291
+ color: var(--ef-tone-action-text);
1292
+ }
1293
+
1294
+ .ef-site .ef-button:is(:disabled, [aria-disabled="true"]) {
1295
+ border-style: dashed;
1296
+ background: var(--ef-color-surface-secondary);
1297
+ color: var(--ef-color-text-primary);
1298
+ cursor: not-allowed;
1299
+ }
1300
+
1301
+ /* Badges ------------------------------------------------------------- */
1302
+ .ef-badge-list {
1303
+ display: flex;
1304
+ flex-wrap: wrap;
1305
+ gap: var(--ef-space-2);
1306
+ margin: var(--ef-space-4) 0;
1307
+ padding: 0;
1308
+ list-style: none;
1309
+ }
1310
+
1311
+ .ef-badge-list > li { margin: 0; }
1312
+
1313
+ .ef-badge {
1314
+ display: inline-flex;
1315
+ align-items: center;
1316
+ gap: var(--ef-space-1);
1317
+ padding: var(--ef-space-1) var(--ef-space-2);
1318
+ border: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1319
+ border-radius: var(--ef-shape-radius);
1320
+ color: var(--ef-tone-text);
1321
+ font-family: var(--ef-type-family-mono);
1322
+ font-size: var(--ef-type-size-label);
1323
+ line-height: var(--ef-type-leading-snug);
1324
+ text-decoration: none;
1325
+ }
1326
+
1327
+ a.ef-badge { min-block-size: 1.5rem; }
1328
+ a.ef-badge:hover { border-color: var(--ef-tone-rule-strong); color: var(--ef-tone-text); }
1329
+
1330
+ /* Status is carried by the badge text; the colored edge is redundant. */
1331
+ .ef-badge[data-ef-status] { border-inline-start-width: var(--ef-shape-border-width-accent); }
1332
+ .ef-badge[data-ef-status="success"] { border-inline-start-color: var(--ef-color-status-success); }
1333
+ .ef-badge[data-ef-status="warning"] { border-inline-start-color: var(--ef-color-status-warning); }
1334
+ .ef-badge[data-ef-status="danger"] { border-inline-start-color: var(--ef-color-status-danger); }
1335
+ .ef-badge[data-ef-status="info"] { border-inline-start-color: var(--ef-color-status-info); }
1336
+
1337
+ /* Cards and card grids ----------------------------------------------- */
1338
+ .ef-card-grid {
1339
+ --ef-card-columns: 12;
1340
+ --ef-card-rule: var(--ef-tone-rule);
1341
+ display: grid;
1342
+ grid-template-columns: repeat(
1343
+ auto-fit,
1344
+ minmax(min(100%, max(var(--ef-layout-card-min), 100% / var(--ef-card-columns))), 1fr)
1345
+ );
1346
+ margin: 0;
1347
+ padding: 0;
1348
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-card-rule);
1349
+ border-inline-start: var(--ef-shape-border-width) solid var(--ef-card-rule);
1350
+ list-style: none;
1351
+ }
1352
+
1353
+ /* data-ef-columns caps columns; the minimum card size decides when to drop. */
1354
+ .ef-card-grid[data-ef-columns="2"] { --ef-card-columns: 2; }
1355
+ .ef-card-grid[data-ef-columns="3"] { --ef-card-columns: 3; }
1356
+ .ef-card-grid[data-ef-columns="4"] { --ef-card-columns: 4; }
1357
+ .ef-card-grid[data-ef-columns="5"] { --ef-card-columns: 5; --ef-layout-card-min: 12rem; }
1358
+
1359
+ .ef-card-grid + .ef-card-grid { border-block-start: 0; }
1360
+ .ef-card-grid > li { margin: 0; }
1361
+
1362
+ .ef-card {
1363
+ position: relative;
1364
+ min-inline-size: 0;
1365
+ padding: var(--ef-layout-block-space);
1366
+ border: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1367
+ border-radius: var(--ef-shape-radius);
1368
+ }
1369
+
1370
+ /* Inside a grid, cards share hairline rules instead of doubling borders. */
1371
+ .ef-card-grid > .ef-card,
1372
+ .ef-card-grid > li > .ef-card {
1373
+ block-size: 100%;
1374
+ border-width: 0 var(--ef-shape-border-width) var(--ef-shape-border-width) 0;
1375
+ border-color: var(--ef-card-rule);
1376
+ border-radius: 0;
1377
+ }
1378
+
1379
+ .ef-card[data-ef-tone="elevated"] { box-shadow: var(--ef-effect-shadow-raised); }
1380
+
1381
+ /* Card titles size by role, not heading level, so the document outline can
1382
+ use whatever level the page needs (VE LAW-COMP-004 hierarchy alignment). */
1383
+ .ef-card__title {
1384
+ max-inline-size: 24ch;
1385
+ margin-block-end: var(--ef-space-3);
1386
+ font-family: var(--ef-type-family-body);
1387
+ font-size: var(--ef-type-size-h3);
1388
+ font-weight: var(--ef-type-weight-strong);
1389
+ letter-spacing: var(--ef-type-tracking-body);
1390
+ line-height: var(--ef-type-leading-snug);
1391
+ }
1392
+
1393
+ /* A card link stretches over the card so the whole card is a target while
1394
+ the accessible name stays the title, not the card's full text. */
1395
+ .ef-card__link {
1396
+ color: inherit;
1397
+ text-decoration: none;
1398
+ }
1399
+
1400
+ .ef-card__link::after {
1401
+ content: "";
1402
+ position: absolute;
1403
+ inset: 0;
1404
+ }
1405
+
1406
+ .ef-card:has(.ef-card__link) { transition: background-color var(--ef-effect-transition-duration) var(--ef-effect-transition-easing); }
1407
+ .ef-card:has(.ef-card__link:hover) { background: var(--ef-tone-hover); }
1408
+ .ef-card__link:hover { color: inherit; text-decoration: underline; }
1409
+ .ef-card__link:focus-visible { box-shadow: none; outline: none; }
1410
+
1411
+ .ef-card:has(.ef-card__link:focus-visible) {
1412
+ outline: var(--ef-focus-ring-width) solid var(--ef-color-focus-gap);
1413
+ outline-offset: calc(var(--ef-focus-ring-offset) * -1 - var(--ef-focus-ring-width));
1414
+ box-shadow: inset 0 0 0 var(--ef-focus-halo-width) var(--ef-color-focus-ring);
1415
+ }
1416
+
1417
+ .ef-card__footer {
1418
+ margin-block-start: var(--ef-space-6);
1419
+ padding-block-start: var(--ef-space-4);
1420
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1421
+ color: var(--ef-tone-text);
1422
+ font-size: var(--ef-type-size-small);
1423
+ font-weight: var(--ef-type-weight-strong);
1424
+ }
1425
+
1426
+ /* Facts: short claims with supporting detail, as a description list. */
1427
+ .ef-facts {
1428
+ display: grid;
1429
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--ef-layout-fact-min)), 1fr));
1430
+ margin: var(--ef-layout-block-space) 0 0;
1431
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1432
+ border-inline-start: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1433
+ }
1434
+
1435
+ .ef-facts__item {
1436
+ min-inline-size: 0;
1437
+ padding: var(--ef-space-4);
1438
+ border-inline-end: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1439
+ border-block-end: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1440
+ }
1441
+
1442
+ .ef-facts__item > dt { color: var(--ef-tone-text); font-weight: var(--ef-type-weight-strong); }
1443
+
1444
+ .ef-facts__item > dd {
1445
+ margin: var(--ef-space-1) 0 0;
1446
+ color: var(--ef-tone-muted);
1447
+ font-size: var(--ef-type-size-small);
1448
+ }
1449
+
1450
+ /* Section heading ---------------------------------------------------- */
1451
+ .ef-section-heading {
1452
+ display: flex;
1453
+ flex-wrap: wrap;
1454
+ align-items: flex-end;
1455
+ justify-content: space-between;
1456
+ gap: var(--ef-space-6) var(--ef-layout-grid-gap);
1457
+ margin-block-end: calc(var(--ef-layout-block-space) * 1.25);
1458
+ padding-block-end: var(--ef-space-6);
1459
+ border-block-end: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1460
+ }
1461
+
1462
+ .ef-section-heading__text { flex: 999 1 32rem; min-inline-size: min(100%, 20rem); }
1463
+ .ef-section-heading__text > :where(h2) { margin-block-end: var(--ef-space-4); }
1464
+ .ef-section-heading__aside { flex: 1 1 14rem; max-inline-size: 28rem; }
1465
+
1466
+ .ef-section-heading__note {
1467
+ color: var(--ef-tone-muted);
1468
+ font-family: var(--ef-type-family-mono);
1469
+ font-size: var(--ef-type-size-label);
1470
+ }
1471
+
1472
+ /* Index: an ordered set of linked entries (research areas, products). */
1473
+ .ef-index {
1474
+ container: ef-index / inline-size;
1475
+ display: grid;
1476
+ grid-template-columns: 5rem minmax(0, 0.65fr) minmax(0, 1fr) minmax(0, auto);
1477
+ column-gap: var(--ef-layout-block-space);
1478
+ margin: 0;
1479
+ padding: 0;
1480
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1481
+ list-style: none;
1482
+ }
1483
+
1484
+ /* Rows share the list's columns (subgrid) so entries align down the page. */
1485
+ .ef-index__item {
1486
+ display: grid;
1487
+ grid-column: 1 / -1;
1488
+ grid-template-columns: subgrid;
1489
+ row-gap: var(--ef-space-2);
1490
+ align-items: start;
1491
+ margin: 0;
1492
+ padding-block: var(--ef-space-7);
1493
+ border-block-end: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1494
+ }
1495
+
1496
+ .ef-index__marker {
1497
+ margin: 0;
1498
+ color: var(--ef-tone-text);
1499
+ font-family: var(--ef-type-family-mono);
1500
+ font-size: var(--ef-type-size-label);
1501
+ }
1502
+
1503
+ .ef-index__title {
1504
+ margin-block-start: var(--ef-space-1);
1505
+ font-family: var(--ef-type-family-display);
1506
+ font-size: var(--ef-type-size-statement);
1507
+ font-weight: var(--ef-type-weight-heading);
1508
+ }
1509
+
1510
+ .ef-index__heading > .ef-eyebrow { margin: 0; }
1511
+ .ef-index__summary { margin: 0; }
1512
+
1513
+ .ef-index__link {
1514
+ display: inline-flex;
1515
+ align-items: center;
1516
+ min-block-size: 1.5rem;
1517
+ font-size: var(--ef-type-size-small);
1518
+ font-weight: var(--ef-type-weight-strong);
1519
+ white-space: nowrap;
1520
+ }
1521
+
1522
+ /* Four disparate columns cannot degrade by a minimum item size, so the
1523
+ row regroups by container width: marker + content, then single column. */
1524
+ @container ef-index (inline-size < 56rem) {
1525
+ .ef-index__item { grid-template-columns: 3.5rem minmax(0, 1fr); column-gap: var(--ef-space-4); }
1526
+ .ef-index__item > :not(.ef-index__marker) { grid-column: 2; }
1527
+ }
1528
+
1529
+ @container ef-index (inline-size < 28rem) {
1530
+ .ef-index__item { grid-template-columns: minmax(0, 1fr); }
1531
+ .ef-index__item > :not(.ef-index__marker) { grid-column: 1; }
1532
+ }
1533
+
1534
+ /* Steps: a numbered method or process. */
1535
+ .ef-steps {
1536
+ counter-reset: ef-step;
1537
+ margin: 0;
1538
+ padding: 0;
1539
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1540
+ list-style: none;
1541
+ }
1542
+
1543
+ .ef-steps > li {
1544
+ counter-increment: ef-step;
1545
+ display: flex;
1546
+ gap: var(--ef-space-4);
1547
+ margin: 0;
1548
+ padding-block: var(--ef-space-4);
1549
+ border-block-end: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1550
+ color: var(--ef-tone-text);
1551
+ }
1552
+
1553
+ .ef-steps > li::before {
1554
+ content: counter(ef-step, decimal-leading-zero);
1555
+ flex: none;
1556
+ min-inline-size: 2ch;
1557
+ font-family: var(--ef-type-family-mono);
1558
+ font-weight: var(--ef-type-weight-strong);
1559
+ }
1560
+
1561
+ /* Call to action ----------------------------------------------------- */
1562
+ .ef-cta {
1563
+ display: flex;
1564
+ flex-wrap: wrap;
1565
+ align-items: flex-end;
1566
+ justify-content: space-between;
1567
+ gap: var(--ef-space-6) var(--ef-layout-grid-gap);
1568
+ padding-block-start: calc(var(--ef-layout-block-space) * 1.25);
1569
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1570
+ }
1571
+
1572
+ .ef-cta__text { flex: 999 1 32rem; min-inline-size: min(100%, 20rem); }
1573
+ .ef-cta__text > :where(h2) { margin-block-end: var(--ef-space-4); }
1574
+ .ef-cta > .ef-actions { flex: 1 1 auto; justify-content: flex-start; }
1575
+
1576
+ .ef-cta[data-ef-tone]:not([data-ef-tone="page"]) {
1577
+ padding: calc(var(--ef-layout-block-space) * 2);
1578
+ border-block-start: 0;
1579
+ }
1580
+
1581
+ /* Prose: long-form content inside the reading measure. */
1582
+ .ef-prose {
1583
+ --ef-type-size-h2: var(--ef-type-size-statement);
1584
+ max-inline-size: var(--ef-layout-measure);
1585
+ }
1586
+
1587
+ .ef-prose > :where(h1) { margin-block-end: var(--ef-space-6); max-inline-size: none; }
1588
+ .ef-prose > :where(h2) { margin-block: var(--ef-space-8) var(--ef-space-5); max-inline-size: none; }
1589
+ .ef-prose > :where(h3) { margin-block: var(--ef-space-7) var(--ef-space-3); }
1590
+ .ef-prose > :where(h2, h3):first-child { margin-block-start: 0; }
1591
+ .ef-prose :where(p, li) { color: var(--ef-tone-text); }
1592
+ .ef-prose > :where(figure, pre, .ef-code) { margin-block: var(--ef-layout-block-space); }
1593
+
1594
+ /* Callout: emphasized supporting material inside prose (FORMA-CONTENT-001).
1595
+ A visible text label names the kind; the rule pattern repeats it as a
1596
+ second, non-color cue. Presentation only: no state and no runtime. */
1597
+ .ef-callout {
1598
+ --ef-callout-rule: var(--ef-tone-rule-strong);
1599
+ margin: var(--ef-layout-block-space) 0;
1600
+ padding: var(--ef-space-4) var(--ef-space-5);
1601
+ max-inline-size: var(--ef-layout-measure);
1602
+ border: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1603
+ border-inline-start: var(--ef-shape-border-width-accent) solid var(--ef-callout-rule);
1604
+ color: var(--ef-tone-text);
1605
+ }
1606
+
1607
+ .ef-callout > :first-child { margin-block-start: 0; }
1608
+ .ef-callout > :last-child { margin-block-end: 0; }
1609
+ .ef-callout :where(p, li) { color: var(--ef-tone-text); max-inline-size: none; }
1610
+
1611
+ .ef-callout__label {
1612
+ margin-block: 0 var(--ef-space-2);
1613
+ color: var(--ef-tone-label);
1614
+ font-family: var(--ef-type-family-mono);
1615
+ font-size: var(--ef-type-size-label);
1616
+ font-weight: var(--ef-type-weight-strong);
1617
+ letter-spacing: var(--ef-type-tracking-label);
1618
+ text-transform: uppercase;
1619
+ }
1620
+
1621
+ /* Quoted evidence reads as body text; the callout already marks it. */
1622
+ .ef-callout :where(blockquote) {
1623
+ margin: 0;
1624
+ padding: 0;
1625
+ border: 0;
1626
+ font-family: inherit;
1627
+ font-size: inherit;
1628
+ line-height: inherit;
1629
+ }
1630
+
1631
+ .ef-callout :where(figcaption) {
1632
+ margin-block-start: var(--ef-space-3);
1633
+ color: var(--ef-tone-muted);
1634
+ font-size: var(--ef-type-size-small);
1635
+ }
1636
+
1637
+ /* Caution: a heavy block-start rule and a full-strength frame. */
1638
+ .ef-callout[data-ef-callout="caution"] {
1639
+ --ef-callout-rule: var(--ef-color-status-warning);
1640
+ border-color: var(--ef-tone-rule-strong);
1641
+ border-block-start-width: var(--ef-shape-border-width-accent);
1642
+ border-inline-start-color: var(--ef-callout-rule);
1643
+ }
1644
+
1645
+ /* Evidence: a dashed frame marks quoted or cited source material. */
1646
+ .ef-callout[data-ef-callout="evidence"] {
1647
+ --ef-callout-rule: var(--ef-color-status-info);
1648
+ border-style: dashed;
1649
+ border-inline-start-style: solid;
1650
+ }
1651
+
1652
+ /* Decision: a double rule marks a settled outcome. */
1653
+ .ef-callout[data-ef-callout="decision"] {
1654
+ --ef-callout-rule: var(--ef-color-accent-primary);
1655
+ border-inline-start-style: double;
1656
+ border-inline-start-width: calc(var(--ef-shape-border-width-accent) * 2);
1657
+ }
1658
+
1659
+ /* Code: technical samples in a bounded, keyboard-scrollable region. */
1660
+ .ef-code {
1661
+ margin: 0;
1662
+ max-inline-size: 100%;
1663
+ overflow: auto;
1664
+ padding: var(--ef-layout-block-space);
1665
+ border-radius: var(--ef-shape-radius);
1666
+ background: var(--ef-color-surface-inverse);
1667
+ color: var(--ef-color-text-inverse);
1668
+ font-family: var(--ef-type-family-mono);
1669
+ font-size: var(--ef-type-size-small);
1670
+ line-height: var(--ef-type-leading-lead);
1671
+ tab-size: 2;
1672
+ }
1673
+
1674
+ .ef-code :where(code) { padding: 0; background: none; color: inherit; font-size: inherit; overflow-wrap: normal; }
1675
+
1676
+ .ef-code-figure { margin: 0; }
1677
+
1678
+ .ef-code-figure > figcaption {
1679
+ margin-block-end: var(--ef-space-2);
1680
+ color: var(--ef-tone-muted);
1681
+ font-family: var(--ef-type-family-mono);
1682
+ font-size: var(--ef-type-size-label);
1683
+ }
1684
+
1685
+ /* Site footer -------------------------------------------------------- */
1686
+ .ef-site-footer {
1687
+ margin-block-start: auto;
1688
+ }
1689
+
1690
+ .ef-site-footer__inner {
1691
+ inline-size: min(100%, var(--ef-layout-width-max));
1692
+ margin-inline: auto;
1693
+ padding: calc(var(--ef-layout-block-space) * 2) var(--ef-layout-gutter);
1694
+ }
1695
+
1696
+ .ef-site-footer__main {
1697
+ display: flex;
1698
+ flex-wrap: wrap;
1699
+ justify-content: space-between;
1700
+ gap: var(--ef-layout-grid-gap);
1701
+ }
1702
+
1703
+ .ef-site-footer__main > * { flex: 1 1 18rem; }
1704
+ .ef-site-footer__main > .ef-actions { flex-grow: 0; }
1705
+
1706
+ .ef-site-footer__nav ul {
1707
+ display: flex;
1708
+ flex-wrap: wrap;
1709
+ gap: var(--ef-space-1) var(--ef-space-5);
1710
+ margin: 0;
1711
+ padding: 0;
1712
+ list-style: none;
1713
+ }
1714
+
1715
+ .ef-site-footer__nav li { margin: 0; }
1716
+ .ef-site-footer__nav a { display: inline-flex; align-items: center; min-block-size: 1.5rem; }
1717
+
1718
+ .ef-site-footer__note {
1719
+ display: flex;
1720
+ flex-wrap: wrap;
1721
+ justify-content: space-between;
1722
+ gap: var(--ef-space-2) var(--ef-space-7);
1723
+ max-inline-size: none;
1724
+ margin: calc(var(--ef-layout-block-space) * 1.5) 0 0;
1725
+ padding-block-start: var(--ef-space-4);
1726
+ border-block-start: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1727
+ color: var(--ef-tone-muted);
1728
+ font-family: var(--ef-type-family-mono);
1729
+ font-size: var(--ef-type-size-label);
1730
+ }
1731
+
1732
+ /* Accessibility and output modes ------------------------------------ */
1733
+ @media (prefers-reduced-motion: reduce) {
1734
+ .ef-site :where(*, *::before, *::after) {
1735
+ scroll-behavior: auto !important;
1736
+ transition: none !important;
1737
+ animation: none !important;
1738
+ }
1739
+ }
1740
+
1741
+ @media (forced-colors: active) {
1742
+ .ef-site-header__mark,
1743
+ .ef-site [data-ef-tone]:not([data-ef-tone="page"]),
1744
+ .ef-code { border: 1px solid CanvasText; }
1745
+ .ef-site .ef-button,
1746
+ .ef-badge,
1747
+ .ef-site-nav__link[data-ef-variant="action"] { border: 1px solid ButtonText; }
1748
+ .ef-site-nav__link[aria-current] { border-block-end-color: Highlight; }
1749
+ .ef-statement { border-block-start-color: CanvasText; }
1750
+ .ef-callout { border-color: CanvasText; }
1751
+ }
1752
+
1753
+ @media print {
1754
+ .ef-site::before,
1755
+ .ef-skip-link,
1756
+ .ef-site-nav,
1757
+ .ef-site-footer .ef-actions { display: none; }
1758
+ .ef-site-header { position: static; backdrop-filter: none; background: none; }
1759
+ .ef-site [data-ef-tone] { background: none; color: CanvasText; }
1760
+ .ef-site :where(h1, h2, h3, h4, p, li, dt, dd, a) { color: CanvasText; }
1761
+ .ef-prose a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; }
1762
+ .ef-card, .ef-index__item, .ef-code, .ef-callout { break-inside: avoid; }
1763
+ .ef-callout { border-color: CanvasText; }
1764
+ }
1765
+ }
1766
+
1767
+ /* --- source: src/marketing/layouts.css --- */
1768
+ /*
1769
+ Forma marketing layouts.
1770
+
1771
+ Page-level structure for public/marketing sites. The MarketingShell
1772
+ (.ef-site) owns the frame: skip link, header, main, footer, and common
1773
+ behavior. Page layouts (Marketing, Product, Documentation) are compositions
1774
+ of the same components inside that frame; only the documentation layout
1775
+ needs structure of its own.
1776
+
1777
+ Breakpoints, and why each exists:
1778
+ - Sticky header needs min-width 40rem and min-height 36rem. A sticky header
1779
+ on a short or narrow viewport (or at 200-400% zoom) permanently consumes
1780
+ reading space and can obscure focused content (WCAG 2.4.11).
1781
+ - The documentation layout regroups at 48rem and 72rem of main-region
1782
+ width (container queries): three regions with different roles cannot
1783
+ share one minimum item size. Below 48rem the navigation list also wraps
1784
+ like a cluster, so a tall vertical nav never pushes the article below
1785
+ the fold.
1786
+ All other recomposition is content-driven (flex-wrap / auto-fit minimums).
1787
+ */
1788
+ @layer echelon.marketing.layouts {
1789
+ @media (min-width: 40rem) and (min-height: 36rem) {
1790
+ .ef-site-header { position: sticky; inset-block-start: 0; }
1791
+ }
1792
+
1793
+ .ef-site__main {
1794
+ flex: 1 0 auto;
1795
+ inline-size: min(100%, var(--ef-layout-width-max));
1796
+ margin-inline: auto;
1797
+ padding-inline: var(--ef-layout-gutter);
1798
+ padding-block-end: var(--ef-layout-section-space);
1799
+ }
1800
+
1801
+ .ef-site__main:focus { outline: none; }
1802
+
1803
+ /* Containers constrain a region inside the page width. */
1804
+ .ef-container {
1805
+ inline-size: min(100%, var(--ef-container-width, var(--ef-layout-width-standard)));
1806
+ margin-inline: auto;
1807
+ }
1808
+
1809
+ .ef-container[data-ef-width="narrow"] { --ef-container-width: var(--ef-layout-width-narrow); }
1810
+ .ef-container[data-ef-width="wide"] { --ef-container-width: var(--ef-layout-width-wide); }
1811
+ .ef-container[data-ef-width="max"] { --ef-container-width: var(--ef-layout-width-max); }
1812
+
1813
+ /* Sections: consistent vertical rhythm between page regions. */
1814
+ .ef-site .ef-section {
1815
+ padding-block: calc(var(--ef-layout-section-space) / 2);
1816
+ }
1817
+
1818
+ .ef-site .ef-section[data-ef-tone]:not([data-ef-tone="page"]) {
1819
+ margin-block: calc(var(--ef-layout-section-space) / 2);
1820
+ padding: calc(var(--ef-layout-block-space) * 2);
1821
+ }
1822
+
1823
+ .ef-section > * + * { margin-block-start: var(--ef-layout-stack-space); }
1824
+ .ef-section > .ef-section-heading + * { margin-block-start: 0; }
1825
+
1826
+ /* Split: primary content with a supporting column that wraps below it. */
1827
+ .ef-split {
1828
+ display: flex;
1829
+ flex-wrap: wrap;
1830
+ align-items: flex-start;
1831
+ gap: calc(var(--ef-layout-section-space) / 2);
1832
+ }
1833
+
1834
+ .ef-split > :first-child { flex: 999 1 0; min-inline-size: min(100%, 55%); }
1835
+ .ef-split > :last-child:not(:first-child) { flex: 1 1 clamp(18rem, 32%, 30rem); min-inline-size: 0; }
1836
+
1837
+ /* Hero: the page's first region and its one primary recognition path. */
1838
+ .ef-hero {
1839
+ display: flex;
1840
+ flex-wrap: wrap;
1841
+ align-items: flex-end;
1842
+ gap: calc(var(--ef-layout-section-space) / 2);
1843
+ padding-block: var(--ef-layout-section-space) calc(var(--ef-layout-block-space) * 2);
1844
+ border-block-end: var(--ef-shape-border-width) solid var(--ef-tone-rule-strong);
1845
+ }
1846
+
1847
+ .ef-hero__content { flex: 999 1 0; min-inline-size: min(100%, 55%); }
1848
+ .ef-hero__aside { flex: 1 1 clamp(18rem, 32%, 30rem); min-inline-size: 0; }
1849
+ .ef-hero__content > * + *,
1850
+ .ef-hero__aside > * + * { margin-block-start: var(--ef-layout-stack-space); }
1851
+ .ef-hero__title { margin-block: var(--ef-space-2) var(--ef-space-6); }
1852
+ .ef-hero__content > .ef-eyebrow + .ef-hero__title { margin-block-start: 0; }
1853
+
1854
+ /* Documentation page: navigation, article, optional page outline.
1855
+ Three regions with different roles cannot share one minimum size, so
1856
+ the grid regroups by the width of the main region (a container):
1857
+ one column, then navigation + article (outline follows the article),
1858
+ then all three. Source order and reading order never change. */
1859
+ .ef-site__main { container: ef-main / inline-size; }
1860
+
1861
+ .ef-doc {
1862
+ container: ef-doc / inline-size;
1863
+ display: grid;
1864
+ grid-template-columns: minmax(0, 1fr);
1865
+ gap: var(--ef-layout-block-space) calc(var(--ef-layout-section-space) / 2);
1866
+ align-items: start;
1867
+ padding-block: calc(var(--ef-layout-section-space) / 2);
1868
+ }
1869
+
1870
+ .ef-doc__nav,
1871
+ .ef-doc__content,
1872
+ .ef-doc__aside { min-inline-size: 0; }
1873
+
1874
+ .ef-doc__content { --ef-type-size-h1: var(--ef-type-size-h2); }
1875
+
1876
+ @container ef-main (inline-size >= 48rem) {
1877
+ .ef-doc { grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr); }
1878
+ .ef-doc__aside { grid-column: 2; }
1879
+ }
1880
+
1881
+ @container ef-main (inline-size >= 72rem) {
1882
+ .ef-doc { grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr) minmax(10rem, 14rem); }
1883
+ .ef-doc__aside { grid-column: 3; }
1884
+ }
1885
+
1886
+ .ef-doc__nav :where(ul),
1887
+ .ef-doc__aside :where(ul) {
1888
+ margin: 0;
1889
+ padding: 0;
1890
+ border-inline-start: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1891
+ list-style: none;
1892
+ }
1893
+
1894
+ .ef-doc__nav :where(li + li),
1895
+ .ef-doc__aside :where(li + li) { margin-block-start: 0; }
1896
+
1897
+ .ef-doc__nav :where(a),
1898
+ .ef-doc__aside :where(a) {
1899
+ display: flex;
1900
+ align-items: center;
1901
+ min-block-size: var(--ef-layout-target-min);
1902
+ margin-inline-start: calc(var(--ef-shape-border-width) * -1);
1903
+ padding-inline: var(--ef-space-4);
1904
+ border-inline-start: calc(var(--ef-shape-border-width) * 2) solid transparent;
1905
+ color: var(--ef-tone-text);
1906
+ font-size: var(--ef-type-size-small);
1907
+ text-decoration: none;
1908
+ }
1909
+
1910
+ .ef-doc__nav :where(a:hover),
1911
+ .ef-doc__aside :where(a:hover) { border-inline-start-color: var(--ef-color-accent-primary); }
1912
+
1913
+ .ef-doc__nav :where(a[aria-current]) {
1914
+ border-inline-start-color: var(--ef-tone-rule-strong);
1915
+ font-weight: var(--ef-type-weight-strong);
1916
+ }
1917
+
1918
+ .ef-doc__heading { margin-block-end: var(--ef-space-2); }
1919
+
1920
+ @media (min-width: 64rem) and (min-height: 36rem) {
1921
+ .ef-doc__nav,
1922
+ .ef-doc__aside {
1923
+ position: sticky;
1924
+ inset-block-start: var(--ef-layout-header-offset);
1925
+ max-block-size: calc(100vh - var(--ef-layout-header-offset) - 1rem);
1926
+ overflow: auto;
1927
+ }
1928
+ }
1929
+
1930
+ @container ef-doc (inline-size < 48rem) {
1931
+ .ef-doc__nav :where(ul) {
1932
+ display: flex;
1933
+ flex-wrap: wrap;
1934
+ gap: 0 var(--ef-space-1);
1935
+ border-inline-start: 0;
1936
+ border-block-end: var(--ef-shape-border-width) solid var(--ef-tone-rule);
1937
+ }
1938
+
1939
+ .ef-doc__nav :where(a) {
1940
+ margin-inline-start: 0;
1941
+ border-inline-start: 0;
1942
+ border-block-end: calc(var(--ef-shape-border-width) * 2) solid transparent;
1943
+ }
1944
+
1945
+ .ef-doc__nav :where(a[aria-current]) { border-block-end-color: var(--ef-tone-rule-strong); }
1946
+ }
1947
+ }