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