@echelon-foundry/design-system 0.13.0 → 0.13.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,28 @@ published as GitHub release tarballs
7
7
  and to npm. Earlier releases are described in `docs/CONSUMING-FORMA.md` and
8
8
  `HANDOFF.md`.
9
9
 
10
+ ## 0.13.1
11
+
12
+ Patch release with two fixes:
13
+
14
+ - marketing containment (MKT-CONTAIN, WI-0043), found by the Echelon Diagnostic Framework site migration to 0.13.0;
15
+ - the record header's type label below 24em (GH-179, WI-0044), found by Signal's upgrade to 0.13.0.
16
+
17
+ No class, token, element or attribute was removed or renamed.
18
+
19
+ ### Fixed
20
+ - **Text containment in marketing components.** LRP-001 (0.13.0) passed `overflow-wrap: break-word` only to the application containers. Marketing components hold the same kind of content, so list items, spans and divs inside them could still escape: on 0.13.0 a release URL in a `span` escaped `.ef-card` by 160px at 320px, and at 200% text ordinary list words ("explanations", "propagation") escaped a card by up to 18px. `.ef-site` now passes `break-word` from `.ef-hero`, `.ef-section-heading`, `.ef-card`, `.ef-facts`, `.ef-index`, `.ef-callout`, `.ef-cta`, `.ef-split`, `.ef-doc`, `.ef-prose`, `.ef-statement` and `.ef-site-footer`. Words that fit are never split; declared values (badges, steps, code) are unchanged.
21
+ - **Record header type label below 24em (GH-179).** In 0.13.0 the header's `@container (max-width: 24em)` rule dropped the title grid's rows, but the identity block stayed `grid-template-rows: subgrid`, so the type label collapsed onto the title. It overlapped by 120–145px at 320–375px and by up to 790px at 200% text in the LRP-001 fixture, and in Signal it overlapped the page title on phones. The identity block now uses its own implicit rows below 24em, so the label sits above the title as it did in 0.6.1. Nothing changes above 24em.
22
+ - **Toned CTA at narrow widths.** `.ef-cta[data-ef-tone]` caps its inline padding at `12.5vw`, as a toned `.ef-section` already does (ULI-L05). At 320px and 200% text the uncapped padding left a 96px content box. Nothing changes at the default text size.
23
+
24
+ ### Added
25
+ - **Optional requirement identity (FMO-019).** `Forma.Workflow.RequirementIdentity` (EchelonFoundry.Forma.Workflow, additive public API) puts `data-requirement-id` (and `data-requirement-instance` for repeated controls) on the element of a component's kind. It refuses wrappers, labels and unrelated elements, ambiguous markup, re-identification and invalid IDs, and it detects duplicate identities in a scope. `contracts/machine-operability.json` 1.1.0 adds `requirementIdentity` under locator tier 3. The attribute is optional and application-owned (FMO-013 unchanged), and no existing markup changes.
26
+
27
+ ### Tests
28
+ - `tests/workflow/Forma.Workflow.Tests/RequirementIdentityTests.fs` (11 cases) and `tests/browser/requirement-identity.spec.mjs` with the generated `tests/browser/fixture/requirement-identity.html`: placement on the control, untouched attributes, label association and role, stability across re-render, refusal of unrelated or ambiguous elements, instance keys, duplicate detection, hidden and disabled states.
29
+ - `tests/browser/layout-reliability.spec.mjs`: the record header's type label ends at or above its title at 320, 375, 768 and 1280px with default and 200% text (GH-179). It fails on 0.13.0 at five of those eight points; containment could not see the defect because both boxes stay inside the header.
30
+ - `tests/browser/marketing-containment.spec.mjs` with `tests/browser/fixture/marketing-containment.html`: containment of every marketing container at 320, 375, 768 and 1280px with default and 200% text, the toned-CTA line length, and that fitting words in cards are not split. Nine of its ten tests fail on 0.13.0.
31
+
10
32
  ## 0.13.0
11
33
 
12
34
  Minor release: layout reliability (LRP-001). The source document is `.praxis/inbox/documents/2026-10-30-LRP-001-layout-reliability.md`; the baseline and the Indy Init report are in `docs/reliability/`. `@echelon-foundry/forma-conformance` 0.3.0 ships the new geometry checks.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "format": "forma.color-contract/1.0.0",
3
- "formaVersion": "0.13.0",
3
+ "formaVersion": "0.13.1",
4
4
  "validationScope": "CSS var() references to --ef-color-* plus reserved internal color-related prefixes; other Forma APIs are governed by their own contracts.",
5
5
  "compatibility": {
6
6
  "policy": "Validate with the contract shipped by the pinned Forma package version.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forma-machine-operability",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "referenceAutomation": "Playwright",
5
5
  "toolNeutral": true,
6
6
  "principle": "Every human-operable action has a deterministic semantically discoverable machine-operable path to the same authoritative application state.",
@@ -44,5 +44,30 @@
44
44
  "forma": "semantic markup, accessible naming, public structure and presentation-state hooks",
45
45
  "applicationOrLimen": "behavior beyond native HTML and application state synchronization",
46
46
  "ordoOrDomain": "legality, capabilities, obligations, permissions and consequential transitions"
47
+ },
48
+ "requirementIdentity": {
49
+ "requirement": "FMO-019",
50
+ "required": false,
51
+ "owner": "application",
52
+ "locatorTier": "documented-application-owned-stable-object-identity",
53
+ "attribute": "data-requirement-id",
54
+ "instanceAttribute": "data-requirement-instance",
55
+ "placement": "on the element of the component's kind (the input, textarea, select, button, link, display or region itself), never on a wrapper, label or unrelated element",
56
+ "components": {
57
+ "text-input": "input of type text, search, email, url, tel, number, date, datetime-local or password",
58
+ "textarea": "textarea",
59
+ "select": "select",
60
+ "checkbox": "input type=checkbox",
61
+ "button": "button, or input type=submit|button",
62
+ "link": "a[href]",
63
+ "display": "dd, dt, time, output, p, span, strong, data, li, td, h1-h4",
64
+ "region": "section, form, fieldset, main, nav, aside, dialog"
65
+ },
66
+ "scope": "one element per ID per active scope; repeated controls carry distinct data-requirement-instance keys",
67
+ "neverReplaces": [
68
+ "role-and-accessible-name",
69
+ "native-label-id-name-value-or-url-target"
70
+ ],
71
+ "implementation": "Forma.Workflow.RequirementIdentity (EchelonFoundry.Forma.Workflow)"
47
72
  }
48
73
  }
package/dist/all.css CHANGED
@@ -3241,7 +3241,10 @@
3241
3241
  .ef-record-header__title > :not(:first-child) { grid-row: 2; }
3242
3242
  @container (max-width: 24em) {
3243
3243
  .ef-record-header__title { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
3244
- .ef-record-header__title > :first-child { grid-row: auto; }
3244
+ /* The title grid has no rows here, so the identity block cannot stay a
3245
+ subgrid: it would collapse the type label onto the title (GH-179).
3246
+ Its own implicit rows keep the label above the title. */
3247
+ .ef-record-header__title > :first-child { grid-row: auto; grid-template-rows: none; }
3245
3248
  .ef-record-header__title > :not(:first-child) { grid-row: auto; justify-self: start; }
3246
3249
  }
3247
3250
  .ef-record-header__title h2 { margin: 0.15rem 0 0; }
@@ -8056,6 +8059,23 @@
8056
8059
  overflow-wrap: anywhere;
8057
8060
  }
8058
8061
 
8062
+ /*
8063
+ * Marketing containment (MKT-CONTAIN, WI-0043). LRP-001 passes
8064
+ * overflow-wrap: break-word to arbitrary content inside the application
8065
+ * containers; marketing components hold the same kind of content (list
8066
+ * items, spans and divs that the element rule above does not reach), so
8067
+ * they pass it on too. break-word never splits a word that fits and leaves
8068
+ * min-content sizes alone; declared values (badges, steps, code) win over
8069
+ * inheritance. Found by the EDF site at 320px: list words escaped a card at
8070
+ * 200% text and a release URL in a span escaped it at every width.
8071
+ */
8072
+ .ef-site :where(
8073
+ .ef-hero, .ef-section-heading, .ef-card, .ef-facts, .ef-index, .ef-callout,
8074
+ .ef-cta, .ef-split, .ef-doc, .ef-prose, .ef-statement, .ef-site-footer
8075
+ ) {
8076
+ overflow-wrap: break-word;
8077
+ }
8078
+
8059
8079
  .ef-site :where(hr) {
8060
8080
  margin-block: var(--ef-layout-section-space);
8061
8081
  border: 0;
@@ -8637,6 +8657,10 @@
8637
8657
 
8638
8658
  .ef-cta[data-ef-tone]:not([data-ef-tone="page"]) {
8639
8659
  padding: calc(var(--ef-layout-block-space) * 2);
8660
+ /* Same cap as a toned .ef-section (ULI-L05): at 320px and 200% text the
8661
+ uncapped inline padding left a 96px content box (MKT-CONTAIN). It
8662
+ changes nothing at the default text size. */
8663
+ padding-inline: min(calc(var(--ef-layout-block-space) * 2), 12.5vw);
8640
8664
  border-block-start: 0;
8641
8665
  }
8642
8666
 
@@ -342,12 +342,12 @@
342
342
  "tokens.css"
343
343
  ],
344
344
  "bytes": {
345
- "all.css": 344943,
345
+ "all.css": 346279,
346
346
  "assessment.css": 36343,
347
347
  "brands/echelon.css": 4213,
348
348
  "brands/example-harbor.css": 4229,
349
349
  "brands/index.json": 335,
350
- "components.css": 214119,
350
+ "components.css": 214359,
351
351
  "foundations.css": 22874,
352
352
  "icons/add.svg": 216,
353
353
  "icons/agent.svg": 354,
@@ -510,7 +510,7 @@
510
510
  "icons/warning.svg": 324,
511
511
  "icons/wifi-off.svg": 269,
512
512
  "icons/workflow.svg": 345,
513
- "marketing.css": 47868,
513
+ "marketing.css": 48964,
514
514
  "patterns/active-filter-summary.html": 532,
515
515
  "patterns/alert.html": 384,
516
516
  "patterns/allocation.html": 1033,
@@ -2182,7 +2182,10 @@
2182
2182
  .ef-record-header__title > :not(:first-child) { grid-row: 2; }
2183
2183
  @container (max-width: 24em) {
2184
2184
  .ef-record-header__title { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
2185
- .ef-record-header__title > :first-child { grid-row: auto; }
2185
+ /* The title grid has no rows here, so the identity block cannot stay a
2186
+ subgrid: it would collapse the type label onto the title (GH-179).
2187
+ Its own implicit rows keep the label above the title. */
2188
+ .ef-record-header__title > :first-child { grid-row: auto; grid-template-rows: none; }
2186
2189
  .ef-record-header__title > :not(:first-child) { grid-row: auto; justify-self: start; }
2187
2190
  }
2188
2191
  .ef-record-header__title h2 { margin: 0.15rem 0 0; }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "formaVersion": "0.13.0",
3
+ "formaVersion": "0.13.1",
4
4
  "grid": 24,
5
5
  "icons": [
6
6
  {
@@ -1,4 +1,4 @@
1
- /*! Forma 0.13.0 | forma-all.css | bundle echelon-marketing
1
+ /*! Forma 0.13.1 | forma-all.css | bundle echelon-marketing
2
2
  Complete Forma surface (application components, assessment, and marketing layers) for sites that also present Forma application patterns such as data grids or status lozenges.
3
3
  Generated by tools/PresentationBundler. Do not edit; pin by version and sha256. */
4
4
 
@@ -3246,7 +3246,10 @@
3246
3246
  .ef-record-header__title > :not(:first-child) { grid-row: 2; }
3247
3247
  @container (max-width: 24em) {
3248
3248
  .ef-record-header__title { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
3249
- .ef-record-header__title > :first-child { grid-row: auto; }
3249
+ /* The title grid has no rows here, so the identity block cannot stay a
3250
+ subgrid: it would collapse the type label onto the title (GH-179).
3251
+ Its own implicit rows keep the label above the title. */
3252
+ .ef-record-header__title > :first-child { grid-row: auto; grid-template-rows: none; }
3250
3253
  .ef-record-header__title > :not(:first-child) { grid-row: auto; justify-self: start; }
3251
3254
  }
3252
3255
  .ef-record-header__title h2 { margin: 0.15rem 0 0; }
@@ -8061,6 +8064,23 @@
8061
8064
  overflow-wrap: anywhere;
8062
8065
  }
8063
8066
 
8067
+ /*
8068
+ * Marketing containment (MKT-CONTAIN, WI-0043). LRP-001 passes
8069
+ * overflow-wrap: break-word to arbitrary content inside the application
8070
+ * containers; marketing components hold the same kind of content (list
8071
+ * items, spans and divs that the element rule above does not reach), so
8072
+ * they pass it on too. break-word never splits a word that fits and leaves
8073
+ * min-content sizes alone; declared values (badges, steps, code) win over
8074
+ * inheritance. Found by the EDF site at 320px: list words escaped a card at
8075
+ * 200% text and a release URL in a span escaped it at every width.
8076
+ */
8077
+ .ef-site :where(
8078
+ .ef-hero, .ef-section-heading, .ef-card, .ef-facts, .ef-index, .ef-callout,
8079
+ .ef-cta, .ef-split, .ef-doc, .ef-prose, .ef-statement, .ef-site-footer
8080
+ ) {
8081
+ overflow-wrap: break-word;
8082
+ }
8083
+
8064
8084
  .ef-site :where(hr) {
8065
8085
  margin-block: var(--ef-layout-section-space);
8066
8086
  border: 0;
@@ -8642,6 +8662,10 @@
8642
8662
 
8643
8663
  .ef-cta[data-ef-tone]:not([data-ef-tone="page"]) {
8644
8664
  padding: calc(var(--ef-layout-block-space) * 2);
8665
+ /* Same cap as a toned .ef-section (ULI-L05): at 320px and 200% text the
8666
+ uncapped inline padding left a 96px content box (MKT-CONTAIN). It
8667
+ changes nothing at the default text size. */
8668
+ padding-inline: min(calc(var(--ef-layout-block-space) * 2), 12.5vw);
8645
8669
  border-block-start: 0;
8646
8670
  }
8647
8671
 
@@ -1,4 +1,4 @@
1
- /*! Forma 0.13.0 | forma-echelon-marketing.css | bundle echelon-marketing
1
+ /*! Forma 0.13.1 | forma-echelon-marketing.css | bundle echelon-marketing
2
2
  Single-file Echelon marketing presentation: forma-marketing.css followed by the Echelon theme. Most sites load only this file.
3
3
  Generated by tools/PresentationBundler. Do not edit; pin by version and sha256. */
4
4
 
@@ -1353,6 +1353,23 @@
1353
1353
  overflow-wrap: anywhere;
1354
1354
  }
1355
1355
 
1356
+ /*
1357
+ * Marketing containment (MKT-CONTAIN, WI-0043). LRP-001 passes
1358
+ * overflow-wrap: break-word to arbitrary content inside the application
1359
+ * containers; marketing components hold the same kind of content (list
1360
+ * items, spans and divs that the element rule above does not reach), so
1361
+ * they pass it on too. break-word never splits a word that fits and leaves
1362
+ * min-content sizes alone; declared values (badges, steps, code) win over
1363
+ * inheritance. Found by the EDF site at 320px: list words escaped a card at
1364
+ * 200% text and a release URL in a span escaped it at every width.
1365
+ */
1366
+ .ef-site :where(
1367
+ .ef-hero, .ef-section-heading, .ef-card, .ef-facts, .ef-index, .ef-callout,
1368
+ .ef-cta, .ef-split, .ef-doc, .ef-prose, .ef-statement, .ef-site-footer
1369
+ ) {
1370
+ overflow-wrap: break-word;
1371
+ }
1372
+
1356
1373
  .ef-site :where(hr) {
1357
1374
  margin-block: var(--ef-layout-section-space);
1358
1375
  border: 0;
@@ -1935,6 +1952,10 @@
1935
1952
 
1936
1953
  .ef-cta[data-ef-tone]:not([data-ef-tone="page"]) {
1937
1954
  padding: calc(var(--ef-layout-block-space) * 2);
1955
+ /* Same cap as a toned .ef-section (ULI-L05): at 320px and 200% text the
1956
+ uncapped inline padding left a 96px content box (MKT-CONTAIN). It
1957
+ changes nothing at the default text size. */
1958
+ padding-inline: min(calc(var(--ef-layout-block-space) * 2), 12.5vw);
1938
1959
  border-block-start: 0;
1939
1960
  }
1940
1961
 
@@ -1,4 +1,4 @@
1
- /*! Forma 0.13.0 | forma-marketing-theme-echelon.css | bundle echelon-marketing
1
+ /*! Forma 0.13.1 | forma-marketing-theme-echelon.css | bundle echelon-marketing
2
2
  Echelon Marketing Theme: compiled theme tokens and theme hooks. Load after forma-marketing.css.
3
3
  Generated by tools/PresentationBundler. Do not edit; pin by version and sha256. */
4
4
 
@@ -1,4 +1,4 @@
1
- /*! Forma 0.13.0 | forma-marketing.css | bundle echelon-marketing
1
+ /*! Forma 0.13.1 | forma-marketing.css | bundle echelon-marketing
2
2
  Brand-neutral marketing layer: core tokens, role defaults, Forma foundations, marketing foundations, components, and layouts.
3
3
  Generated by tools/PresentationBundler. Do not edit; pin by version and sha256. */
4
4
 
@@ -1352,6 +1352,23 @@
1352
1352
  overflow-wrap: anywhere;
1353
1353
  }
1354
1354
 
1355
+ /*
1356
+ * Marketing containment (MKT-CONTAIN, WI-0043). LRP-001 passes
1357
+ * overflow-wrap: break-word to arbitrary content inside the application
1358
+ * containers; marketing components hold the same kind of content (list
1359
+ * items, spans and divs that the element rule above does not reach), so
1360
+ * they pass it on too. break-word never splits a word that fits and leaves
1361
+ * min-content sizes alone; declared values (badges, steps, code) win over
1362
+ * inheritance. Found by the EDF site at 320px: list words escaped a card at
1363
+ * 200% text and a release URL in a span escaped it at every width.
1364
+ */
1365
+ .ef-site :where(
1366
+ .ef-hero, .ef-section-heading, .ef-card, .ef-facts, .ef-index, .ef-callout,
1367
+ .ef-cta, .ef-split, .ef-doc, .ef-prose, .ef-statement, .ef-site-footer
1368
+ ) {
1369
+ overflow-wrap: break-word;
1370
+ }
1371
+
1355
1372
  .ef-site :where(hr) {
1356
1373
  margin-block: var(--ef-layout-section-space);
1357
1374
  border: 0;
@@ -1934,6 +1951,10 @@
1934
1951
 
1935
1952
  .ef-cta[data-ef-tone]:not([data-ef-tone="page"]) {
1936
1953
  padding: calc(var(--ef-layout-block-space) * 2);
1954
+ /* Same cap as a toned .ef-section (ULI-L05): at 320px and 200% text the
1955
+ uncapped inline padding left a 96px content box (MKT-CONTAIN). It
1956
+ changes nothing at the default text size. */
1957
+ padding-inline: min(calc(var(--ef-layout-block-space) * 2), 12.5vw);
1937
1958
  border-block-start: 0;
1938
1959
  }
1939
1960
 
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "forma": "0.13.0",
3
+ "forma": "0.13.1",
4
4
  "bundle": "echelon-marketing",
5
5
  "description": "Forma presentation artifacts for Echelon marketing sites. Every artifact is a single self-contained CSS file with no imports or relative URLs.",
6
- "releaseTag": "v0.13.0",
6
+ "releaseTag": "v0.13.1",
7
7
  "artifacts": [
8
8
  {
9
9
  "file": "forma-marketing.css",
10
10
  "description": "Brand-neutral marketing layer: core tokens, role defaults, Forma foundations, marketing foundations, components, and layouts.",
11
- "bytes": 95041,
12
- "sha256": "a2248c09b9c7731178f3046a245541fb240715c12b21638300d56a4fdd61819d",
11
+ "bytes": 96137,
12
+ "sha256": "77ed356b74ee190e0ae1181fd83c4308d159f60e16bc93e3fc89b893c1f06ebc",
13
13
  "sources": [
14
14
  "dist/tokens.css",
15
15
  "src/marketing/roles.css",
@@ -23,7 +23,7 @@
23
23
  "file": "forma-marketing-theme-echelon.css",
24
24
  "description": "Echelon Marketing Theme: compiled theme tokens and theme hooks. Load after forma-marketing.css.",
25
25
  "bytes": 6296,
26
- "sha256": "0b803cade4de294a2e15ac8a8482cb2448617a2558d70fc6542a4b3b9a357bf2",
26
+ "sha256": "6801950c7438a1274dc4a8cb24d642f67d0d8e67be3e8a9e1e037a0734078fc4",
27
27
  "sources": [
28
28
  "build/marketing/echelon-marketing.tokens.css",
29
29
  "themes/echelon/marketing.css"
@@ -32,8 +32,8 @@
32
32
  {
33
33
  "file": "forma-echelon-marketing.css",
34
34
  "description": "Single-file Echelon marketing presentation: forma-marketing.css followed by the Echelon theme. Most sites load only this file.",
35
- "bytes": 101181,
36
- "sha256": "cdf0ebfa0b60219e72d1c32dc0ac068d73255654748b55283bbb1c7a9db78a7f",
35
+ "bytes": 102277,
36
+ "sha256": "92803ba115f644b36800a6a26b0162dad927aa051792e88f9713d0bafac01e73",
37
37
  "sources": [
38
38
  "artifact:forma-marketing.css",
39
39
  "artifact:forma-marketing-theme-echelon.css"
@@ -42,8 +42,8 @@
42
42
  {
43
43
  "file": "forma-all.css",
44
44
  "description": "Complete Forma surface (application components, assessment, and marketing layers) for sites that also present Forma application patterns such as data grids or status lozenges.",
45
- "bytes": 345306,
46
- "sha256": "403d708505fc3fe2ac7bd2c78220e98ad9236a5c82f76d1b88d7a9c4b01ee213",
45
+ "bytes": 346642,
46
+ "sha256": "0a0919db3accd32e2663266c69604cc7e3c47f3c1e96a3067ce3a58e67126734",
47
47
  "sources": [
48
48
  "dist/all.css"
49
49
  ]
@@ -1,4 +1,4 @@
1
- a2248c09b9c7731178f3046a245541fb240715c12b21638300d56a4fdd61819d forma-marketing.css
2
- 0b803cade4de294a2e15ac8a8482cb2448617a2558d70fc6542a4b3b9a357bf2 forma-marketing-theme-echelon.css
3
- cdf0ebfa0b60219e72d1c32dc0ac068d73255654748b55283bbb1c7a9db78a7f forma-echelon-marketing.css
4
- 403d708505fc3fe2ac7bd2c78220e98ad9236a5c82f76d1b88d7a9c4b01ee213 forma-all.css
1
+ 77ed356b74ee190e0ae1181fd83c4308d159f60e16bc93e3fc89b893c1f06ebc forma-marketing.css
2
+ 6801950c7438a1274dc4a8cb24d642f67d0d8e67be3e8a9e1e037a0734078fc4 forma-marketing-theme-echelon.css
3
+ 92803ba115f644b36800a6a26b0162dad927aa051792e88f9713d0bafac01e73 forma-echelon-marketing.css
4
+ 0a0919db3accd32e2663266c69604cc7e3c47f3c1e96a3067ce3a58e67126734 forma-all.css
@@ -285,6 +285,23 @@
285
285
  overflow-wrap: anywhere;
286
286
  }
287
287
 
288
+ /*
289
+ * Marketing containment (MKT-CONTAIN, WI-0043). LRP-001 passes
290
+ * overflow-wrap: break-word to arbitrary content inside the application
291
+ * containers; marketing components hold the same kind of content (list
292
+ * items, spans and divs that the element rule above does not reach), so
293
+ * they pass it on too. break-word never splits a word that fits and leaves
294
+ * min-content sizes alone; declared values (badges, steps, code) win over
295
+ * inheritance. Found by the EDF site at 320px: list words escaped a card at
296
+ * 200% text and a release URL in a span escaped it at every width.
297
+ */
298
+ .ef-site :where(
299
+ .ef-hero, .ef-section-heading, .ef-card, .ef-facts, .ef-index, .ef-callout,
300
+ .ef-cta, .ef-split, .ef-doc, .ef-prose, .ef-statement, .ef-site-footer
301
+ ) {
302
+ overflow-wrap: break-word;
303
+ }
304
+
288
305
  .ef-site :where(hr) {
289
306
  margin-block: var(--ef-layout-section-space);
290
307
  border: 0;
@@ -866,6 +883,10 @@
866
883
 
867
884
  .ef-cta[data-ef-tone]:not([data-ef-tone="page"]) {
868
885
  padding: calc(var(--ef-layout-block-space) * 2);
886
+ /* Same cap as a toned .ef-section (ULI-L05): at 320px and 200% text the
887
+ uncapped inline padding left a 96px content box (MKT-CONTAIN). It
888
+ changes nothing at the default text size. */
889
+ padding-inline: min(calc(var(--ef-layout-block-space) * 2), 12.5vw);
869
890
  border-block-start: 0;
870
891
  }
871
892
 
package/dist/runtime.js CHANGED
@@ -52,6 +52,6 @@ export function registerEchelonRuntime(name, metadata, target = globalThis) {
52
52
  return installEchelonRuntimeRegistrar(target)?.(name, metadata);
53
53
  }
54
54
 
55
- export const FORMA_VERSION = "0.13.0";
55
+ export const FORMA_VERSION = "0.13.1";
56
56
 
57
57
  if (typeof window !== "undefined") registerEchelonRuntime("forma", { version: FORMA_VERSION }, window);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@echelon-foundry/design-system",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Zero-component-runtime HTML and CSS design system for Echelon Foundry applications.",