@echelon-foundry/design-system 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -208,7 +208,10 @@
208
208
 
209
209
  /* Choice cards -------------------------------------------------------- */
210
210
  .ef-choice-group {
211
- display: grid;
211
+ /* A column flex layout lets wrapped cards determine their own height.
212
+ WebKit can retain stale grid row heights on fieldset viewport reflow. */
213
+ display: flex;
214
+ flex-direction: column;
212
215
  gap: var(--ef-primitive-spacing-2, 0.5rem);
213
216
  }
214
217
 
@@ -708,6 +711,7 @@
708
711
 
709
712
  .ef-semantic-differential__endpoints {
710
713
  display: flex;
714
+ flex-wrap: wrap;
711
715
  justify-content: space-between;
712
716
  gap: 1rem;
713
717
  margin-block-end: 0.4rem;
@@ -923,6 +927,9 @@
923
927
  }
924
928
 
925
929
  .ef-best-worst__row + .ef-best-worst__row { border-block-start: 0; }
930
+ /* A long unbroken option (a product code, a compound word) wraps inside
931
+ its track instead of scrolling the page sideways (ULI-L05). */
932
+ .ef-best-worst__row > :first-child { min-inline-size: 0; overflow-wrap: anywhere; }
926
933
  .ef-best-worst__row label { display: grid; place-items: center; min-block-size: 2.75rem; }
927
934
  .ef-best-worst__row input { inline-size: 1.25rem; block-size: 1.25rem; accent-color: var(--ef-color-accent-primary, #905831); }
928
935
 
@@ -1021,6 +1028,10 @@
1021
1028
  padding-inline: 0.75rem;
1022
1029
  }
1023
1030
 
1031
+ /* Desktop labels align at the top of their own row. In the horizontal
1032
+ mobile layout that override must not defeat marker/text centering. */
1033
+ .ef-ordinal-option__label { align-self: center; }
1034
+
1024
1035
  .ef-ordinal-option + .ef-ordinal-option {
1025
1036
  border-inline-start: 0;
1026
1037
  border-block-start: 1px solid var(--ef-color-border-subtle, #e3e0d7);
@@ -1033,7 +1044,7 @@
1033
1044
  }
1034
1045
 
1035
1046
  .ef-rule-clause { grid-template-columns: 1fr; }
1036
- .ef-obligation { grid-template-columns: 1fr; }
1047
+ .ef-obligation { grid-template-columns: minmax(0, 1fr); }
1037
1048
  .ef-obligation__status { justify-self: start; }
1038
1049
 
1039
1050
  .ef-ranking__item {
@@ -231,6 +231,7 @@
231
231
  "patterns/file-upload.html",
232
232
  "patterns/flyout.html",
233
233
  "patterns/focus-stage.html",
234
+ "patterns/form-row.html",
234
235
  "patterns/frame.html",
235
236
  "patterns/freshness.html",
236
237
  "patterns/grid.html",
@@ -339,13 +340,13 @@
339
340
  "tokens.css"
340
341
  ],
341
342
  "bytes": {
342
- "all.css": 317501,
343
- "assessment.css": 35692,
343
+ "all.css": 326931,
344
+ "assessment.css": 36343,
344
345
  "brands/echelon.css": 3621,
345
346
  "brands/example-harbor.css": 3637,
346
347
  "brands/index.json": 335,
347
- "components.css": 204251,
348
- "foundations.css": 11558,
348
+ "components.css": 209407,
349
+ "foundations.css": 14098,
349
350
  "icons/add.svg": 216,
350
351
  "icons/agent.svg": 354,
351
352
  "icons/archive.svg": 248,
@@ -507,7 +508,7 @@
507
508
  "icons/warning.svg": 324,
508
509
  "icons/wifi-off.svg": 269,
509
510
  "icons/workflow.svg": 345,
510
- "marketing.css": 45073,
511
+ "marketing.css": 46156,
511
512
  "patterns/active-filter-summary.html": 532,
512
513
  "patterns/alert.html": 384,
513
514
  "patterns/allocation.html": 1033,
@@ -570,6 +571,7 @@
570
571
  "patterns/file-upload.html": 867,
571
572
  "patterns/flyout.html": 2488,
572
573
  "patterns/focus-stage.html": 377,
574
+ "patterns/form-row.html": 848,
573
575
  "patterns/frame.html": 365,
574
576
  "patterns/freshness.html": 187,
575
577
  "patterns/grid.html": 305,
@@ -26,9 +26,44 @@
26
26
  min-inline-size: 0;
27
27
  max-inline-size: 100%;
28
28
  grid-template-columns: minmax(0, 1fr);
29
+ /* A stretched field (a grid row taller than it) keeps its label and
30
+ control at the top instead of distributing the extra space between
31
+ rows, which would push the control below its peers (ULI-L01). */
32
+ align-content: start;
29
33
  gap: var(--ef-primitive-spacing-2, 0.5rem);
30
34
  }
31
35
 
36
+ /*
37
+ * Form row (ULI-L01, L03, L13). Peer fields share one set of rows: label,
38
+ * description, control and validation message. Each field spans the four
39
+ * rows through subgrid and places its parts explicitly, so every control
40
+ * in a visual row starts at the same top edge however long the labels,
41
+ * descriptions or messages of its neighbours are. Fields wrap to new rows
42
+ * by available width. Without subgrid support each field keeps its own
43
+ * grid (the previous behavior).
44
+ */
45
+ .ef-form-row {
46
+ --ef-form-row-min: 14rem;
47
+ display: grid;
48
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--ef-form-row-min)), 1fr));
49
+ column-gap: var(--ef-form-row-gap, var(--ef-primitive-spacing-4, 1rem));
50
+ row-gap: 0;
51
+ align-items: start;
52
+ min-inline-size: 0;
53
+ }
54
+
55
+ .ef-form-row > .ef-field {
56
+ grid-row: span 4;
57
+ grid-template-rows: subgrid;
58
+ row-gap: 0;
59
+ margin-block-end: var(--ef-form-row-gap, var(--ef-primitive-spacing-4, 1rem));
60
+ }
61
+
62
+ .ef-form-row > .ef-field > .ef-field__label { grid-row: 1; }
63
+ .ef-form-row > .ef-field > .ef-field__description { grid-row: 2; margin-block-start: var(--ef-primitive-spacing-2, 0.5rem); }
64
+ .ef-form-row > .ef-field > :not(.ef-field__label, .ef-field__description, .ef-validation-message) { grid-row: 3; margin-block-start: var(--ef-primitive-spacing-2, 0.5rem); }
65
+ .ef-form-row > .ef-field > .ef-validation-message { grid-row: 4; margin-block-start: var(--ef-primitive-spacing-2, 0.5rem); }
66
+
32
67
  .ef-field > :is(input[type="date"], input[type="time"], input[type="datetime-local"]) {
33
68
  min-inline-size: 0;
34
69
  inline-size: 100%;
@@ -67,6 +102,10 @@
67
102
  --ef-motion-perceptual-emphasis-duration: var(--ef-primitive-motion-duration-standard, 180ms);
68
103
  --ef-motion-perceptual-easing: var(--ef-primitive-motion-easing-standard, cubic-bezier(0.2, 0, 0, 1));
69
104
 
105
+ /* Brief surface fade: gentle ignition, fast middle, gentle settling.
106
+ Monotonic and symmetric: no opacity overshoot or delayed activation. */
107
+ --ef-motion-fade-easing: cubic-bezier(0.65, 0, 0.35, 1);
108
+
70
109
  /* Constant-velocity cadence: repeated activity is parameterized by a
71
110
  named period and constant velocity, never by spring settling (MOT-016). */
72
111
  --ef-motion-cadence-period: 1600ms;
@@ -96,7 +135,7 @@
96
135
  --ef-motion-gravity-duration: 255ms;
97
136
  --ef-motion-state-duration: 154ms;
98
137
  --ef-motion-press-duration: 107ms;
99
- --ef-motion-exit-duration: 146ms;
138
+ --ef-motion-exit-duration: 214ms;
100
139
  --ef-motion-spring-easing: linear(0, 0.42 24%, 0.82 48%, 1.055 70%, 0.988 88%, 1);
101
140
  --ef-motion-damped-easing: cubic-bezier(0.2, 0.8, 0.2, 1);
102
141
  }
@@ -170,11 +209,8 @@
170
209
  calc(var(--ef-motion-inertia-duration) * 0.5),
171
210
  160ms
172
211
  );
173
- --ef-motion-exit-duration: clamp(
174
- 80ms,
175
- calc(var(--ef-motion-inertia-duration) * 0.68),
176
- 220ms
177
- );
212
+ /* Compatibility token: reciprocal motion has one response time. */
213
+ --ef-motion-exit-duration: var(--ef-motion-inertia-duration);
178
214
  }
179
215
  }
180
216
 
@@ -358,7 +394,9 @@
358
394
 
359
395
  /* Select -------------------------------------------------------------- */
360
396
  .ef-select-field {
397
+ min-inline-size: 0;
361
398
  display: grid;
399
+ grid-template-columns: minmax(0, 1fr);
362
400
  gap: var(--ef-primitive-spacing-2, 0.5rem);
363
401
  max-inline-size: 100%;
364
402
  }
@@ -366,12 +404,19 @@
366
404
  .ef-select {
367
405
  --ef-motion-distance: 0.35;
368
406
  position: relative;
407
+ min-inline-size: 0;
369
408
  display: grid;
409
+ grid-template-columns: minmax(0, 1fr);
370
410
  align-items: center;
371
411
  max-inline-size: 100%;
372
412
  }
373
413
 
374
414
  .ef-select__input {
415
+ overflow: hidden;
416
+ text-overflow: ellipsis;
417
+ white-space: nowrap;
418
+ min-inline-size: 0;
419
+ max-inline-size: 100%;
375
420
  inline-size: 100%;
376
421
  min-block-size: 2.75rem;
377
422
  padding-inline-end: 2.75rem;
@@ -590,6 +635,10 @@
590
635
 
591
636
  .ef-disclosure > summary {
592
637
  min-inline-size: 0;
638
+ /* The open marker rotates 45deg; its rotated (empty) box corners would
639
+ otherwise add a few pixels of page overflow at narrow widths (ULI-L05).
640
+ Clipping does not affect the summary's own focus ring. */
641
+ overflow-x: clip;
593
642
  display: flex;
594
643
  align-items: center;
595
644
  justify-content: space-between;
@@ -643,35 +692,19 @@
643
692
  overflow: auto;
644
693
  overscroll-behavior: contain;
645
694
  opacity: 0;
646
- translate: 0 -0.35rem;
647
- scale: 0.985;
648
- transition:
649
- opacity var(--ef-motion-perceptual-duration) var(--ef-motion-perceptual-easing),
650
- translate var(--ef-motion-exit-duration) var(--ef-motion-damped-easing),
651
- scale var(--ef-motion-exit-duration) var(--ef-motion-damped-easing),
652
- display var(--ef-motion-exit-duration) allow-discrete,
653
- overlay var(--ef-motion-exit-duration) allow-discrete;
695
+ /* Fade at the resting geometry. Never translate or scale a visible exit. */
696
+ transition: opacity var(--ef-motion-perceptual-duration) var(--ef-motion-fade-easing);
654
697
  }
655
698
 
656
699
  .ef-popover:popover-open,
657
700
  .ef-menu:popover-open {
658
701
  opacity: 1;
659
- translate: 0 0;
660
- scale: 1;
661
- transition-duration:
662
- var(--ef-motion-perceptual-duration),
663
- var(--ef-motion-inertia-duration),
664
- var(--ef-motion-inertia-duration),
665
- var(--ef-motion-inertia-duration),
666
- var(--ef-motion-inertia-duration);
667
702
  }
668
703
 
669
704
  @starting-style {
670
705
  .ef-popover:popover-open,
671
706
  .ef-menu:popover-open {
672
707
  opacity: 0;
673
- translate: 0 -0.35rem;
674
- scale: 0.985;
675
708
  }
676
709
  }
677
710
 
@@ -723,9 +756,9 @@
723
756
  * the hint stays inside the viewport; otherwise the browser's centered
724
757
  * top-layer popover placement remains readable and in view.
725
758
  *
726
- * Motion: light perceived weight. Opacity is perceptual interpolation and
727
- * a tiny origin-related displacement is light inertial; exit uses the
728
- * shorter derived exit duration. Reduced motion removes the displacement.
759
+ * Motion: reciprocal perceptual fades at unchanged resting geometry. The
760
+ * top layer is removed only after opacity reaches zero where supported.
761
+ * Reduced motion reaches the endpoint immediately.
729
762
  */
730
763
  .ef-tooltip {
731
764
  --ef-motion-distance: 0.2;
@@ -744,7 +777,6 @@
744
777
  }
745
778
 
746
779
  .ef-tooltip__surface {
747
- --ef-tooltip-offset: 0.25rem;
748
780
  inline-size: max-content;
749
781
  max-inline-size: min(20rem, calc(100vw - 2rem));
750
782
  margin: 0;
@@ -756,30 +788,30 @@
756
788
  line-height: 1.4;
757
789
  overflow-wrap: anywhere;
758
790
  opacity: 0;
759
- translate: 0 var(--ef-tooltip-offset);
760
- transition:
761
- opacity var(--ef-motion-perceptual-duration) var(--ef-motion-perceptual-easing),
762
- translate var(--ef-motion-exit-duration) var(--ef-motion-damped-easing),
763
- display var(--ef-motion-exit-duration) allow-discrete,
764
- overlay var(--ef-motion-exit-duration) allow-discrete;
791
+ transition: opacity var(--ef-motion-perceptual-duration) var(--ef-motion-fade-easing);
765
792
  }
766
793
 
767
794
  .ef-tooltip__surface:popover-open {
768
795
  opacity: 1;
769
- translate: 0 0;
770
- /* Entry settles over the light inertial duration; exit (above) uses the
771
- shorter derived exit duration. Opacity stays perceptual both ways. */
772
- transition-duration:
773
- var(--ef-motion-perceptual-duration),
774
- var(--ef-motion-inertia-duration),
775
- var(--ef-motion-inertia-duration),
776
- var(--ef-motion-inertia-duration);
777
796
  }
778
797
 
779
798
  @starting-style {
780
799
  .ef-tooltip__surface:popover-open {
781
800
  opacity: 0;
782
- translate: 0 var(--ef-tooltip-offset);
801
+ }
802
+ }
803
+
804
+ /* Keep the top-layer placement and implicit anchor through the entire fade.
805
+ Display retention alone can expose a relocated, translucent surface in
806
+ engines without overlay retention. Those engines dismiss immediately. */
807
+ @supports (overlay: auto) {
808
+ .ef-popover,
809
+ .ef-menu,
810
+ .ef-tooltip__surface {
811
+ transition:
812
+ opacity var(--ef-motion-perceptual-duration) var(--ef-motion-fade-easing),
813
+ display var(--ef-motion-perceptual-duration) allow-discrete,
814
+ overlay var(--ef-motion-perceptual-duration) allow-discrete;
783
815
  }
784
816
  }
785
817
 
@@ -802,9 +834,8 @@
802
834
  }
803
835
 
804
836
  @media (prefers-reduced-motion: reduce) {
805
- .ef-tooltip__surface,
806
- .ef-tooltip__surface:popover-open {
807
- translate: 0 0;
837
+ .ef-tooltip__surface {
838
+ transition-duration: 0.01ms;
808
839
  }
809
840
  }
810
841
 
@@ -906,8 +937,8 @@
906
937
 
907
938
  /* Dialog and flyout ---------------------------------------------------- */
908
939
  :where(.ef-dialog, .ef-flyout) {
909
- --ef-overlay-motion-duration: var(--ef-motion-exit-duration);
910
- --ef-overlay-spatial-easing: var(--ef-motion-damped-easing);
940
+ --ef-overlay-motion-duration: var(--ef-motion-inertia-duration);
941
+ --ef-overlay-spatial-easing: var(--ef-motion-spring-easing);
911
942
  padding: 0;
912
943
  border: 1px solid var(--ef-color-border-functional, #3a403c);
913
944
  background: var(--ef-color-surface-primary, #f2efe7);
@@ -926,9 +957,7 @@
926
957
  /* Dimming is non-spatial: perceptual interpolation, without mass. */
927
958
  transition:
928
959
  background var(--ef-motion-perceptual-duration) var(--ef-motion-perceptual-easing),
929
- backdrop-filter var(--ef-motion-perceptual-duration) var(--ef-motion-perceptual-easing),
930
- display var(--ef-overlay-motion-duration) allow-discrete,
931
- overlay var(--ef-overlay-motion-duration) allow-discrete;
960
+ backdrop-filter var(--ef-motion-perceptual-duration) var(--ef-motion-perceptual-easing);
932
961
  }
933
962
 
934
963
  :where(.ef-dialog, .ef-flyout)[open]::backdrop {
@@ -945,9 +974,7 @@
945
974
  scale: 0.985;
946
975
  transition:
947
976
  translate var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing),
948
- scale var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing),
949
- display var(--ef-overlay-motion-duration) allow-discrete,
950
- overlay var(--ef-overlay-motion-duration) allow-discrete;
977
+ scale var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing);
951
978
  }
952
979
 
953
980
  .ef-dialog[open] {
@@ -980,9 +1007,34 @@
980
1007
  box-shadow: 0 0 3rem rgb(0 0 0 / 0.24);
981
1008
  translate: var(--ef-flyout-closed-x) 0;
982
1009
  transition:
983
- translate var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing),
984
- display var(--ef-overlay-motion-duration) allow-discrete,
985
- overlay var(--ef-overlay-motion-duration) allow-discrete;
1010
+ translate var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing);
1011
+ }
1012
+
1013
+ /* Retain display only when overlay can retain viewport/top-layer geometry.
1014
+ Otherwise a closed dialog can animate inside a containing ancestor. */
1015
+ @supports (overlay: auto) {
1016
+ :where(.ef-dialog, .ef-flyout)::backdrop {
1017
+ transition:
1018
+ background var(--ef-motion-perceptual-duration) var(--ef-motion-perceptual-easing),
1019
+ backdrop-filter var(--ef-motion-perceptual-duration) var(--ef-motion-perceptual-easing),
1020
+ display var(--ef-overlay-motion-duration) allow-discrete,
1021
+ overlay var(--ef-overlay-motion-duration) allow-discrete;
1022
+ }
1023
+
1024
+ .ef-dialog {
1025
+ transition:
1026
+ translate var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing),
1027
+ scale var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing),
1028
+ display var(--ef-overlay-motion-duration) allow-discrete,
1029
+ overlay var(--ef-overlay-motion-duration) allow-discrete;
1030
+ }
1031
+
1032
+ .ef-flyout {
1033
+ transition:
1034
+ translate var(--ef-overlay-motion-duration) var(--ef-overlay-spatial-easing),
1035
+ display var(--ef-overlay-motion-duration) allow-discrete,
1036
+ overlay var(--ef-overlay-motion-duration) allow-discrete;
1037
+ }
986
1038
  }
987
1039
 
988
1040
  .ef-flyout[data-ef-side="left"] {
@@ -1004,9 +1056,11 @@
1004
1056
  .ef-flyout[open] { translate: 0 0; }
1005
1057
 
1006
1058
  .ef-flyout__surface {
1059
+ min-inline-size: 0;
1007
1060
  min-block-size: 0;
1008
1061
  block-size: 100%;
1009
1062
  display: grid;
1063
+ grid-template-columns: minmax(0, 1fr);
1010
1064
  grid-template-rows: auto minmax(0, 1fr) auto;
1011
1065
  }
1012
1066
 
@@ -1036,6 +1090,7 @@
1036
1090
  }
1037
1091
 
1038
1092
  .ef-flyout__body {
1093
+ min-inline-size: 0;
1039
1094
  min-block-size: 0;
1040
1095
  overflow: auto;
1041
1096
  overscroll-behavior: contain;
@@ -1129,7 +1184,9 @@
1129
1184
  font-family: var(--ef-primitive-font-family-mono, ui-monospace, monospace);
1130
1185
  font-size: 0.6875rem;
1131
1186
  line-height: 1.2;
1132
- white-space: nowrap;
1187
+ /* Wraps inside its container rather than widening it (ULI-L05). */
1188
+ max-inline-size: 100%;
1189
+ overflow-wrap: anywhere;
1133
1190
  }
1134
1191
 
1135
1192
  .ef-status-lozenge::before {
@@ -1187,7 +1244,7 @@
1187
1244
 
1188
1245
  .ef-collection-toolbar__controls label,
1189
1246
  .ef-collection-toolbar__filters {
1190
- min-inline-size: 9rem;
1247
+ min-inline-size: min(9rem, 100%);
1191
1248
  font-size: 0.75rem;
1192
1249
  font-weight: 650;
1193
1250
  }
@@ -1481,8 +1538,10 @@
1481
1538
  /* Metrics and dashboards --------------------------------------------- */
1482
1539
  .ef-metric-card {
1483
1540
  display: grid;
1541
+ grid-template-columns: minmax(0, 1fr);
1484
1542
  gap: 0.5rem;
1485
1543
  min-inline-size: 0;
1544
+ overflow-wrap: anywhere;
1486
1545
  padding: 1.25rem;
1487
1546
  border: 1px solid var(--ef-color-border-functional, #3a403c);
1488
1547
  background: var(--ef-color-surface-primary, #f2efe7);
@@ -1825,6 +1884,8 @@
1825
1884
  }
1826
1885
 
1827
1886
  .ef-wizard__steps li {
1887
+ min-inline-size: 0;
1888
+ overflow-wrap: anywhere;
1828
1889
  display: flex;
1829
1890
  gap: 0.5rem;
1830
1891
  align-items: center;
@@ -1851,6 +1912,7 @@
1851
1912
  .ef-readiness-checklist > header h3 { margin: 0.5rem 0 0; }
1852
1913
  .ef-readiness-checklist__items { margin: 0; padding: 0; list-style: none; }
1853
1914
  .ef-readiness-checklist__items li {
1915
+ overflow-wrap: anywhere;
1854
1916
  display: grid;
1855
1917
  grid-template-columns: 2rem minmax(0, 1fr) auto;
1856
1918
  gap: 0.75rem;
@@ -1918,6 +1980,7 @@
1918
1980
  .ef-command-palette__group button {
1919
1981
  inline-size: 100%;
1920
1982
  display: flex;
1983
+ flex-wrap: wrap;
1921
1984
  justify-content: space-between;
1922
1985
  gap: 1rem;
1923
1986
  text-align: start;
@@ -2034,13 +2097,38 @@
2034
2097
  }
2035
2098
 
2036
2099
  .ef-record-header__main nav { font-size: 0.75rem; }
2100
+ /*
2101
+ * The status sits beside the record title and is centred on the title's
2102
+ * row, not on the type label and title together (ULI-L01, L07). The
2103
+ * identity block spans two subgrid rows (type, title); the status occupies
2104
+ * the title row. Narrow containers stack the status below.
2105
+ */
2106
+ .ef-record-header__main { container-type: inline-size; min-inline-size: 0; }
2037
2107
  .ef-record-header__title {
2038
- display: flex;
2039
- flex-wrap: wrap;
2040
- gap: 1rem;
2108
+ display: grid;
2109
+ grid-template-columns: minmax(0, auto) auto;
2110
+ grid-template-rows: auto auto;
2111
+ justify-content: start;
2112
+ column-gap: 1rem;
2113
+ row-gap: 0.5rem;
2041
2114
  align-items: center;
2042
2115
  margin-block: 0.75rem 0;
2043
2116
  }
2117
+ .ef-record-header__title > :first-child {
2118
+ display: grid;
2119
+ grid-row: 1 / span 2;
2120
+ grid-template-rows: subgrid;
2121
+ row-gap: 0;
2122
+ min-inline-size: 0;
2123
+ }
2124
+ .ef-record-header__title > :first-child > .ef-record-header__type { grid-row: 1; align-self: end; }
2125
+ .ef-record-header__title > :first-child > :is(h1, h2, h3, h4) { grid-row: 2; }
2126
+ .ef-record-header__title > :not(:first-child) { grid-row: 2; }
2127
+ @container (max-width: 24em) {
2128
+ .ef-record-header__title { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
2129
+ .ef-record-header__title > :first-child { grid-row: auto; }
2130
+ .ef-record-header__title > :not(:first-child) { grid-row: auto; justify-self: start; }
2131
+ }
2044
2132
  .ef-record-header__title h2 { margin: 0.15rem 0 0; }
2045
2133
  .ef-record-header__type {
2046
2134
  color: var(--ef-surface-accent-text-color, var(--ef-color-accent-secondary, #47756b));
@@ -2124,7 +2212,9 @@
2124
2212
  .ef-provenance-trail li {
2125
2213
  position: relative;
2126
2214
  display: grid;
2215
+ grid-template-columns: minmax(0, 1fr);
2127
2216
  gap: 0.2rem;
2217
+ overflow-wrap: anywhere;
2128
2218
  padding: 0.75rem 0 0.75rem 2rem;
2129
2219
  }
2130
2220
  .ef-provenance-trail li::before {
@@ -2184,6 +2274,7 @@
2184
2274
  /* Mobile action bar --------------------------------------------------- */
2185
2275
  .ef-mobile-action-bar {
2186
2276
  display: flex;
2277
+ flex-wrap: wrap;
2187
2278
  gap: 0.5rem;
2188
2279
  padding: 0.75rem;
2189
2280
  padding-block-end: max(0.75rem, env(safe-area-inset-bottom));
@@ -2192,7 +2283,7 @@
2192
2283
  backdrop-filter: blur(10px);
2193
2284
  }
2194
2285
 
2195
- .ef-mobile-action-bar > * { flex: 1 1 0; }
2286
+ .ef-mobile-action-bar > * { flex: 1 1 min(100%, 8rem); }
2196
2287
  .ef-mobile-action-bar__primary {
2197
2288
  background: var(--ef-color-surface-inverse, #202421);
2198
2289
  color: var(--ef-color-text-inverse, #f2efe7);
@@ -2225,7 +2316,9 @@
2225
2316
  .ef-operation-status,
2226
2317
  .ef-record-header,
2227
2318
  .ef-file-upload__queue li {
2228
- grid-template-columns: 1fr;
2319
+ /* minmax(0, …): a long word or wide font never holds the track wider
2320
+ than the screen (ULI-L05). */
2321
+ grid-template-columns: minmax(0, 1fr);
2229
2322
  }
2230
2323
 
2231
2324
  .ef-work-queue__item button,
@@ -2304,6 +2397,7 @@
2304
2397
  margin-block-end: 0.75rem;
2305
2398
  border: 1px solid var(--ef-color-border-functional, #3a403c);
2306
2399
  }
2400
+ .ef-data-grid tr { container-type: inline-size; }
2307
2401
  .ef-data-grid td {
2308
2402
  display: grid;
2309
2403
  grid-template-columns: minmax(6.5rem, 0.4fr) minmax(0, 1fr);
@@ -2317,13 +2411,19 @@
2317
2411
  font-weight: 650;
2318
2412
  }
2319
2413
  .ef-data-grid td[data-label="Actions"] > * { inline-size: 100%; }
2414
+ /* When enlarged text leaves no room for a label beside its value, the
2415
+ label stacks above the value instead of squeezing it to a few
2416
+ characters per line (ULI-L05). 16em is two readable columns. */
2417
+ @container (max-width: 16em) {
2418
+ .ef-data-grid td { grid-template-columns: minmax(0, 1fr); gap: 0.25rem; }
2419
+ }
2320
2420
 
2321
2421
  .ef-search__control { grid-template-columns: 1fr; }
2322
2422
  .ef-search__control input { border-inline-end: 1px solid var(--ef-color-border-functional, #3a403c); border-block-end: 0; }
2323
2423
 
2324
2424
  .ef-work-queue__header { display: grid; }
2325
2425
  .ef-diff-row,
2326
- .ef-key-value-list > div { grid-template-columns: 1fr; gap: 0.25rem; }
2426
+ .ef-key-value-list > div { grid-template-columns: minmax(0, 1fr); gap: 0.25rem; }
2327
2427
 
2328
2428
  .ef-status-lozenge-set { align-items: stretch; }
2329
2429
  .ef-status-lozenge-set .ef-status-lozenge { flex: 1 1 100%; justify-content: center; }
@@ -2565,7 +2665,7 @@
2565
2665
  .ef-composer__actions button { min-block-size: 2.75rem; }
2566
2666
  .ef-composer__submit { inline-size: 100%; }
2567
2667
 
2568
- .ef-turn { grid-template-columns: 1fr; }
2668
+ .ef-turn { grid-template-columns: minmax(0, 1fr); }
2569
2669
  .ef-turn__actions { grid-column: 1; }
2570
2670
  .ef-turn__actions button { inline-size: 100%; }
2571
2671
 
@@ -2848,6 +2948,7 @@
2848
2948
  --ef-color-text-muted: var(--ef-color-text-on-secondary-surface, #3a403c);
2849
2949
  --ef-surface-accent-text-color: var(--ef-color-text-primary, #171a18);
2850
2950
  display: inline-flex;
2951
+ max-inline-size: 100%;
2851
2952
  align-items: center;
2852
2953
  gap: var(--ef-primitive-spacing-2, 0.5rem);
2853
2954
  padding: 0.55rem 0.75rem;
@@ -2866,6 +2967,8 @@
2866
2967
  .ef-diagnostic-status__body {
2867
2968
  display: grid;
2868
2969
  gap: 0.1rem;
2970
+ min-inline-size: 0;
2971
+ overflow-wrap: anywhere;
2869
2972
  }
2870
2973
 
2871
2974
  .ef-diagnostic-status__body > span {
@@ -3004,7 +3107,7 @@
3004
3107
  .ef-security-state-matrix__grid dt { font-size:.75rem; font-weight:700; }
3005
3108
  .ef-security-state-matrix__grid dd { margin:0; font-size:clamp(1.4rem,4vw,2rem); font-weight:750; }
3006
3109
  .ef-security-blockers ul { display:grid; gap:.75rem; padding-inline-start:1.25rem; }
3007
- .ef-security-blockers li { padding-inline-start:.25rem; }
3110
+ .ef-security-blockers li { padding-inline-start:.25rem; min-inline-size:0; overflow-wrap:anywhere; }
3008
3111
  .ef-security-blockers li span { display:block; }
3009
3112
  .ef-security-evidence-chain ol { display:grid; grid-template-columns:repeat(auto-fit,minmax(9rem,1fr)); gap:.5rem; padding:0; list-style:none; }
3010
3113
  .ef-security-evidence-chain li { padding:.75rem; border:1px solid var(--ef-color-border-functional,#3a403c); overflow-wrap:anywhere; }
@@ -3018,7 +3121,7 @@
3018
3121
  .ef-invariant-result dl { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(10rem,100%),1fr)); gap:.75rem; }
3019
3122
  .ef-invariant-result dt { color:var(--ef-color-text-secondary,#686d68); font-size:.75rem; font-weight:700; } .ef-invariant-result dd { margin:0; overflow-wrap:anywhere; }
3020
3123
  :where(.ef-evidence-age,.ef-security-trend) ul { display:grid; gap:.5rem; margin:0; padding:0; list-style:none; }
3021
- :where(.ef-evidence-age,.ef-security-trend) li { --ef-color-text-secondary: var(--ef-color-text-on-secondary-surface, #3a403c); --ef-color-text-muted: var(--ef-color-text-on-secondary-surface, #3a403c); --ef-surface-accent-text-color: var(--ef-color-text-primary, #171a18); display:grid; gap:.2rem; border-inline-start:.3rem solid currentColor; padding:.65rem .75rem; background:var(--ef-color-surface-secondary,#e3e0d7); }
3124
+ :where(.ef-evidence-age,.ef-security-trend) li { grid-template-columns:minmax(0,1fr); min-inline-size:0; overflow-wrap:anywhere; --ef-color-text-secondary: var(--ef-color-text-on-secondary-surface, #3a403c); --ef-color-text-muted: var(--ef-color-text-on-secondary-surface, #3a403c); --ef-surface-accent-text-color: var(--ef-color-text-primary, #171a18); display:grid; gap:.2rem; border-inline-start:.3rem solid currentColor; padding:.65rem .75rem; background:var(--ef-color-surface-secondary,#e3e0d7); }
3022
3125
  :where(.ef-evidence-age,.ef-security-trend) li span { overflow-wrap:anywhere; }
3023
3126
 
3024
3127
  /* Composition primitives ---------------------------------------------- */
@@ -3228,7 +3331,10 @@
3228
3331
  }
3229
3332
 
3230
3333
  @media (max-width: 48rem) {
3231
- .ef-split-pane[data-ef-resizable] { grid-template-columns: minmax(0, 1fr); }
3334
+ /* Includes the collapsed state, whose track list would otherwise keep
3335
+ three columns on a phone and squeeze the secondary pane (ULI-L05). */
3336
+ .ef-split-pane[data-ef-resizable],
3337
+ .ef-split-pane[data-ef-resizable][data-ef-collapsed] { grid-template-columns: minmax(0, 1fr); }
3232
3338
  .ef-split-pane__separator { display: none; }
3233
3339
  }
3234
3340