@starci/grammar 0.17.0 → 0.18.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.
Files changed (63) hide show
  1. package/README.md +25 -7
  2. package/dist/.build-stamp.json +4 -4
  3. package/dist/common/components-forms.css +8 -8
  4. package/dist/common/components-navigation.css +29 -29
  5. package/dist/common/components-overlays.css +13 -15
  6. package/dist/common/components-spacing.css +97 -0
  7. package/dist/common/index.d.ts +1 -1
  8. package/dist/common/index.d.ts.map +1 -1
  9. package/dist/common/index.js +1 -1
  10. package/dist/common/index.js.map +1 -1
  11. package/dist/common/registry.d.ts +11 -0
  12. package/dist/common/registry.d.ts.map +1 -1
  13. package/dist/common/registry.js +2 -1
  14. package/dist/common/registry.js.map +1 -1
  15. package/dist/common/renderers.d.ts +3 -0
  16. package/dist/common/renderers.d.ts.map +1 -1
  17. package/dist/common/renderers.js +3 -0
  18. package/dist/common/renderers.js.map +1 -1
  19. package/dist/common/spacing.d.ts +32 -2
  20. package/dist/common/spacing.d.ts.map +1 -1
  21. package/dist/common/spacing.js +29 -2
  22. package/dist/common/spacing.js.map +1 -1
  23. package/dist/common/styles.css +206 -78
  24. package/dist/core/branch/Rail/index.d.ts +1 -1
  25. package/dist/core/branch/Rail/index.d.ts.map +1 -1
  26. package/dist/core/branch/Rail/index.js +1 -1
  27. package/dist/core/branch/Rail/index.js.map +1 -1
  28. package/dist/core/branch/Tabs/index.d.ts +4 -4
  29. package/dist/core/branch/Tabs/index.d.ts.map +1 -1
  30. package/dist/core/branch/Tabs/index.js +1 -3
  31. package/dist/core/branch/Tabs/index.js.map +1 -1
  32. package/dist/core/composition/Cluster/index.d.ts +23 -0
  33. package/dist/core/composition/Cluster/index.d.ts.map +1 -0
  34. package/dist/core/composition/Cluster/index.js +8 -0
  35. package/dist/core/composition/Cluster/index.js.map +1 -0
  36. package/dist/core/composition/Grid/index.d.ts +32 -0
  37. package/dist/core/composition/Grid/index.d.ts.map +1 -0
  38. package/dist/core/composition/Grid/index.js +19 -0
  39. package/dist/core/composition/Grid/index.js.map +1 -0
  40. package/dist/core/composition/Page/PanesFill.d.ts +11 -0
  41. package/dist/core/composition/Page/PanesFill.d.ts.map +1 -0
  42. package/dist/core/composition/Page/PanesFill.js +12 -0
  43. package/dist/core/composition/Page/PanesFill.js.map +1 -0
  44. package/dist/core/composition/Page/index.d.ts.map +1 -1
  45. package/dist/core/composition/Page/index.js +2 -3
  46. package/dist/core/composition/Page/index.js.map +1 -1
  47. package/dist/core/composition/Stack/index.d.ts +30 -0
  48. package/dist/core/composition/Stack/index.d.ts.map +1 -0
  49. package/dist/core/composition/Stack/index.js +23 -0
  50. package/dist/core/composition/Stack/index.js.map +1 -0
  51. package/dist/core/dna.d.ts +7 -30
  52. package/dist/core/dna.d.ts.map +1 -1
  53. package/dist/core/dna.js +3 -17
  54. package/dist/core/dna.js.map +1 -1
  55. package/dist/core/primitive/Button/index.js +7 -2
  56. package/dist/core/primitive/Button/index.js.map +1 -1
  57. package/dist/core/styles.css +1 -1
  58. package/dist/offset-pop/components-navigation.css +1 -1
  59. package/dist/offset-pop/dna.d.ts +7 -53
  60. package/dist/offset-pop/dna.d.ts.map +1 -1
  61. package/dist/offset-pop/dna.js +3 -17
  62. package/dist/offset-pop/dna.js.map +1 -1
  63. package/package.json +1 -1
@@ -6,25 +6,52 @@
6
6
  @import "./components-navigation.css";
7
7
  @import "./components-list-panel.css";
8
8
  @import "./components-avatar-group.css";
9
+ @import "./components-spacing.css";
9
10
 
10
11
  @layer starci-grammar-common {
11
12
  .grammar-common-root {
13
+ /*
14
+ * THE SPACING SCALE IS 0 4 8 12 24 32 (common/spacing.ts), and every value below names one step by its role.
15
+ * Gaps, by the relation between siblings: identity 4 < inline 8 < row 12 < section 24 < region 32.
16
+ */
17
+ --grammar-identity-gap: 0.25rem;
12
18
  --grammar-inline-gap: 0.5rem;
13
19
  --grammar-row-gap: 0.75rem;
14
- --grammar-section-gap: 1rem;
15
- --grammar-region-gap: 1.5rem;
16
- --grammar-page-inset: clamp(1rem, 3vw, 2rem);
17
- /* Card box padding, one place per axis: SurfaceCard and SurfaceListCard content (PADDING-4). */
18
- --grammar-card-padding-inline: 1rem;
19
- --grammar-card-padding-block: 1rem;
20
+ --grammar-section-gap: 1.5rem;
21
+ --grammar-region-gap: 2rem;
22
+ /*
23
+ * Insets, by the level of the box. Every container (card, pane, overlay, notice, band) holds its content 12 in
24
+ * on every side, so a closed box has equal block sides; a box inside a card takes the nested step (8); a large
25
+ * empty or waiting region takes the open step (24). Extra separation belongs to the parent's gap.
26
+ */
27
+ --grammar-inset: 0.75rem;
28
+ --grammar-inset-nested: 0.5rem;
29
+ --grammar-inset-open: 1.5rem;
30
+ /* The page gutter steps by breakpoint (12, 24 from 48rem, 32 from 70rem), never fluid. */
31
+ --grammar-page-inset: 0.75rem;
32
+ /* Card box padding, one place per axis: SurfaceCard and SurfaceListCard content. */
33
+ --grammar-card-padding-inline: var(--grammar-inset);
34
+ --grammar-card-padding-block: var(--grammar-inset);
35
+ /* Dialog and drawer: header, body and footer share this inset on every side. */
36
+ --grammar-overlay-inset: var(--grammar-inset);
20
37
  /*
21
- * Pane inset, one place per axis. Inline: both pane edges. Block start: the side facing a divider or the page
22
- * band. Block end: the grid's outer bottom edge, or a divider below.
38
+ * Pane inset, one place per side. Inline: both pane edges. Block start: the side facing a divider or the page
39
+ * band. Block end: the grid's outer bottom edge, or a divider below. One value on every side.
23
40
  */
24
- --grammar-pane-inset-inline: 1rem;
25
- --grammar-pane-inset-block-start: 0.75rem;
26
- --grammar-pane-inset-block-end-outer: 1rem;
27
- --grammar-pane-inset-block-end-divider: 0.75rem;
41
+ --grammar-pane-inset-inline: var(--grammar-inset);
42
+ --grammar-pane-inset-block-start: var(--grammar-inset);
43
+ --grammar-pane-inset-block-end-outer: var(--grammar-inset);
44
+ --grammar-pane-inset-block-end-divider: var(--grammar-inset);
45
+ /*
46
+ * Control inline padding by size step (sm 8, md 12, lg 24); the side a leading or trailing glyph sits on takes
47
+ * one step less (sm 4, md 8, lg 12). Block padding is never chosen: the control height derives it.
48
+ */
49
+ --grammar-control-padding-inline-sm: 0.5rem;
50
+ --grammar-control-padding-inline-md: 0.75rem;
51
+ --grammar-control-padding-inline-lg: 1.5rem;
52
+ --grammar-control-padding-glyph-sm: 0.25rem;
53
+ --grammar-control-padding-glyph-md: 0.5rem;
54
+ --grammar-control-padding-glyph-lg: 0.75rem;
28
55
  /* The Mascot scale: square boxes sm 96px, md 160px, lg 240px; the hero fills its host's height up to the cap. */
29
56
  --grammar-mascot-sm: 6rem;
30
57
  --grammar-mascot-md: 10rem;
@@ -35,6 +62,18 @@
35
62
  min-width: 0;
36
63
  }
37
64
 
65
+ @media (min-width: 48rem) {
66
+ .grammar-common-root {
67
+ --grammar-page-inset: 1.5rem;
68
+ }
69
+ }
70
+
71
+ @media (min-width: 70rem) {
72
+ .grammar-common-root {
73
+ --grammar-page-inset: 2rem;
74
+ }
75
+ }
76
+
38
77
  /*
39
78
  * THE ROOT OWNS EVERY VENDOR THEME VARIABLE.
40
79
  *
@@ -260,7 +299,7 @@
260
299
  width: min(100%, var(--starci-core-page-measure, 80rem));
261
300
  min-width: 0;
262
301
  margin-inline: auto;
263
- padding-inline: var(--grammar-page-inset, clamp(1rem, 3vw, 2rem));
302
+ padding-inline: var(--grammar-page-inset, 0.75rem);
264
303
  }
265
304
 
266
305
  .starci-core-page-container[data-grammar-page-measure="reading"] {
@@ -277,7 +316,7 @@
277
316
  flex-wrap: wrap;
278
317
  align-items: flex-end;
279
318
  justify-content: space-between;
280
- gap: var(--grammar-region-gap, 1.5rem);
319
+ gap: var(--grammar-region-gap, 2rem);
281
320
  }
282
321
 
283
322
  /* The copy keeps a readable basis, so a narrow header wraps its action below instead of crushing the copy. */
@@ -355,7 +394,7 @@
355
394
  display: flex;
356
395
  min-width: 0;
357
396
  flex-direction: column;
358
- margin-block-end: var(--grammar-region-gap, 1.5rem);
397
+ margin-block-end: var(--grammar-region-gap, 2rem);
359
398
  background: var(--surface, Canvas);
360
399
  color: var(--surface-foreground, var(--foreground, CanvasText));
361
400
  }
@@ -364,7 +403,7 @@
364
403
  display: flex;
365
404
  flex-direction: column;
366
405
  gap: var(--grammar-row-gap, 0.75rem);
367
- padding-block: var(--grammar-region-gap, 1.5rem);
406
+ padding-block: var(--grammar-section-gap, 1.5rem);
368
407
  }
369
408
 
370
409
  .starci-core-page-header[data-grammar-page-header-tabs="true"] .starci-core-page-header-body {
@@ -378,7 +417,7 @@
378
417
  flex-wrap: wrap;
379
418
  align-items: center;
380
419
  justify-content: space-between;
381
- gap: var(--grammar-row-gap, 0.75rem) var(--grammar-region-gap, 1.5rem);
420
+ gap: var(--grammar-row-gap, 0.75rem) var(--grammar-region-gap, 2rem);
382
421
  }
383
422
 
384
423
  .starci-core-page-header-lead {
@@ -457,7 +496,7 @@
457
496
  /*
458
497
  * Page: the single owner of the page inset and rhythm. The header band runs full width; the body is the page's
459
498
  * PageContainer, one region step below the band (or below the top without one) and one above the bottom, its
460
- * sections a region step apart. The body clips one gutter step (1rem, the least gutter) beyond its content box, so
499
+ * sections a region step apart. The body clips one gutter step (0.75rem, the least gutter) beyond its content box, so
461
500
  * nothing in it (a negative margin, a full-bleed width) reaches across the gutter, while focus rings and card shadows
462
501
  * still draw. Overlays portal to the Grammar root, so the clip never cuts one.
463
502
  */
@@ -465,8 +504,8 @@
465
504
  display: flex;
466
505
  min-width: 0;
467
506
  flex-direction: column;
468
- gap: var(--grammar-region-gap, 1.5rem);
469
- padding-block-end: var(--grammar-region-gap, 1.5rem);
507
+ gap: var(--grammar-region-gap, 2rem);
508
+ padding-block-end: var(--grammar-region-gap, 2rem);
470
509
  }
471
510
 
472
511
  .starci-core-page > .starci-core-page-header {
@@ -474,15 +513,15 @@
474
513
  }
475
514
 
476
515
  .starci-core-page[data-grammar-page-header="false"] {
477
- padding-block-start: var(--grammar-region-gap, 1.5rem);
516
+ padding-block-start: var(--grammar-region-gap, 2rem);
478
517
  }
479
518
 
480
519
  .starci-core-page-body {
481
520
  display: flex;
482
521
  flex-direction: column;
483
- gap: var(--grammar-region-gap, 1.5rem);
522
+ gap: var(--grammar-region-gap, 2rem);
484
523
  overflow: clip;
485
- overflow-clip-margin: content-box 1rem;
524
+ overflow-clip-margin: content-box 0.75rem;
486
525
  }
487
526
 
488
527
  /*
@@ -508,6 +547,8 @@
508
547
  * --starci-core-fill-top and --starci-core-fill-bottom), so the grid reaches the viewport bottom less Grammar bottom chrome.
509
548
  */
510
549
  .starci-core-page[data-grammar-page-chrome="panes"] {
550
+ /* The gutter column starts at the pane content edge: the title, the first tab and the pane content share the container inset (ruling spacing-roles). */
551
+ --grammar-page-inset: var(--grammar-inset, 0.75rem);
511
552
  flex: 1 0 auto;
512
553
  gap: 0;
513
554
  padding-block: 0;
@@ -540,7 +581,7 @@
540
581
  /* Over panes the trail is the band: it ends in the separator the grid attaches to. */
541
582
  .starci-core-page[data-grammar-page-chrome="panes"] > .starci-core-page-trail {
542
583
  padding-block: var(--grammar-pane-inset-block-start, 0.75rem);
543
- padding-inline: var(--grammar-page-inset, 1rem);
584
+ padding-inline: var(--grammar-page-inset, 0.75rem);
544
585
  border-block-end: 1px solid var(--separator, var(--starci-core-separator, GrayText));
545
586
  }
546
587
 
@@ -664,7 +705,7 @@
664
705
  display: grid;
665
706
  min-width: 0;
666
707
  grid-template-columns: minmax(0, 1fr);
667
- gap: var(--grammar-region-gap, 1.5rem);
708
+ gap: var(--grammar-region-gap, 2rem);
668
709
  }
669
710
 
670
711
  .starci-core-primary-rail-layout[data-grammar-layout-align="start"] { align-items: start; }
@@ -690,7 +731,7 @@
690
731
  .starci-core-form-page {
691
732
  display: flex;
692
733
  min-height: 100dvh;
693
- padding: 1.5rem 1rem;
734
+ padding: var(--grammar-section-gap, 1.5rem) var(--grammar-page-inset, 0.75rem);
694
735
  align-items: center;
695
736
  justify-content: center;
696
737
  overflow: hidden;
@@ -707,7 +748,7 @@
707
748
  width: min(100%, var(--starci-core-form-measure, 30rem));
708
749
  min-width: 0;
709
750
  flex-direction: column;
710
- gap: var(--grammar-section-gap, 1rem);
751
+ gap: var(--grammar-row-gap, 0.75rem);
711
752
  }
712
753
 
713
754
  .starci-core-form-surface--compact {
@@ -915,7 +956,7 @@
915
956
 
916
957
  @media (min-width: 40rem) {
917
958
  .starci-core-form-page {
918
- padding-block: 2.5rem;
959
+ padding-block: var(--grammar-region-gap, 2rem);
919
960
  }
920
961
 
921
962
  .starci-core-form-scroll-viewport {
@@ -938,7 +979,7 @@
938
979
  min-width: 0;
939
980
  width: 100%;
940
981
  flex-direction: column;
941
- gap: var(--grammar-section-gap, 1rem);
982
+ gap: var(--grammar-row-gap, 0.75rem);
942
983
  }
943
984
 
944
985
  .starci-core-surface-label {
@@ -1021,7 +1062,7 @@
1021
1062
  min-block-size: 100%;
1022
1063
  block-size: 100%;
1023
1064
  flex-direction: column;
1024
- gap: var(--grammar-region-gap, 1.5rem);
1065
+ gap: var(--grammar-region-gap, 2rem);
1025
1066
  padding: var(--grammar-page-inset, 2rem);
1026
1067
  overflow: hidden;
1027
1068
  background: var(--accent-soft, var(--starci-core-accent-soft, Canvas));
@@ -1106,8 +1147,13 @@
1106
1147
 
1107
1148
  .starci-core-surface-content {
1108
1149
  min-width: 0;
1109
- padding-block: var(--grammar-card-padding-block, 1rem);
1110
- padding-inline: var(--grammar-card-padding-inline, 1rem);
1150
+ padding-block: var(--grammar-card-padding-block, 0.75rem);
1151
+ padding-inline: var(--grammar-card-padding-inline, 0.75rem);
1152
+ }
1153
+
1154
+ /* A box inside a card (a nested card, a stat cell, a notice) is one level in: the nested step on every side. */
1155
+ .starci-core-surface[data-grammar-surface-depth="nested"]:not([data-grammar-surface-composition="joined"], .starci-core-frameless-surface) > .starci-core-surface-content {
1156
+ padding: var(--grammar-inset-nested, 0.5rem);
1111
1157
  }
1112
1158
 
1113
1159
  .starci-core-surface[data-grammar-surface-composition="joined"] > .starci-core-surface-content {
@@ -1238,7 +1284,7 @@
1238
1284
  width: 11.25rem;
1239
1285
  height: 7.5rem;
1240
1286
  margin-block-start: 0.25rem;
1241
- margin-inline: auto -2.5rem;
1287
+ margin-inline: auto calc(-1 * var(--grammar-accent-corner));
1242
1288
  pointer-events: none;
1243
1289
  user-select: none;
1244
1290
  }
@@ -1515,10 +1561,18 @@
1515
1561
  }
1516
1562
 
1517
1563
  .starci-core-tabs-frame[data-grammar-tabs-variant="primary"] .starci-core-tabs .tabs__tab {
1518
- padding-inline: 0.75rem !important;
1564
+ padding-inline: var(--starci-core-tab-padding-start, var(--grammar-inset, 0.75rem)) var(--grammar-inset, 0.75rem) !important;
1519
1565
  padding-block-end: 0 !important;
1520
1566
  }
1521
1567
 
1568
+ /*
1569
+ * Text edge: the first underline tab's label stands on the content edge it shares with the page title and the
1570
+ * card or pane box below; its hit area keeps the end padding, so two labels sit one section step apart.
1571
+ */
1572
+ .starci-core-tabs-frame[data-grammar-tabs-variant="primary"] .starci-core-tabs .tabs__tab:first-child {
1573
+ --starci-core-tab-padding-start: 0px;
1574
+ }
1575
+
1522
1576
  .starci-core-tabs-frame[data-grammar-tabs-variant="primary"] .starci-core-tabs .tabs__indicator {
1523
1577
  bottom: 0 !important;
1524
1578
  height: 2px !important;
@@ -1552,7 +1606,7 @@
1552
1606
  margin: 0;
1553
1607
  align-items: flex-start;
1554
1608
  gap: var(--grammar-row-gap, 0.75rem);
1555
- padding: var(--starci-core-row-inset, 1rem);
1609
+ padding: var(--starci-core-row-inset, var(--grammar-inset, 0.75rem));
1556
1610
  }
1557
1611
 
1558
1612
  .starci-core-static-row + .starci-core-static-row {
@@ -1701,7 +1755,7 @@
1701
1755
  .starci-core-accordion-body {
1702
1756
  width: 100% !important;
1703
1757
  min-width: 0;
1704
- padding: 0 1rem 0.75rem 1.5rem !important;
1758
+ padding: 0 var(--grammar-inset, 0.75rem) var(--grammar-inset, 0.75rem) var(--grammar-section-gap, 1.5rem) !important;
1705
1759
  color: var(--foreground, var(--starci-core-foreground, CanvasText));
1706
1760
  }
1707
1761
 
@@ -1718,7 +1772,7 @@
1718
1772
  width: 100% !important;
1719
1773
  min-width: 0;
1720
1774
  min-height: 44px;
1721
- padding: var(--starci-core-row-inset, 1rem) !important;
1775
+ padding: var(--starci-core-row-inset, var(--grammar-inset, 0.75rem)) !important;
1722
1776
  border: 0;
1723
1777
  background: transparent;
1724
1778
  box-shadow: none;
@@ -1768,7 +1822,7 @@
1768
1822
  width: 100%;
1769
1823
  min-width: 0;
1770
1824
  flex-direction: column;
1771
- gap: 1rem;
1825
+ gap: var(--grammar-row-gap, 0.75rem);
1772
1826
  color: inherit;
1773
1827
  font-size: 0.875rem;
1774
1828
  line-height: 1.65;
@@ -1789,7 +1843,7 @@
1789
1843
  }
1790
1844
 
1791
1845
  .starci-core-markdown-article :where(h1, h2, h3, h4) {
1792
- margin: 1.5rem 0 0.625rem;
1846
+ margin: var(--grammar-section-gap, 1.5rem) 0 var(--grammar-inline-gap, 0.5rem);
1793
1847
  color: inherit;
1794
1848
  font-weight: 600;
1795
1849
  line-height: 1.3;
@@ -1815,12 +1869,12 @@
1815
1869
  .starci-core-markdown-article em { font-style: italic; }
1816
1870
 
1817
1871
  .starci-core-markdown-article li + li {
1818
- margin-top: 0.375rem;
1872
+ margin-top: var(--grammar-identity-gap, 0.25rem);
1819
1873
  }
1820
1874
 
1821
1875
  .starci-core-markdown-article :not(pre) > code {
1822
1876
  display: inline;
1823
- padding: 0.125rem 0.375rem;
1877
+ padding: 0 var(--grammar-identity-gap, 0.25rem);
1824
1878
  border: 1px solid var(--border, GrayText);
1825
1879
  border-radius: 999px;
1826
1880
  background: var(--muted-surface, color-mix(in srgb, CanvasText 7%, Canvas));
@@ -1833,7 +1887,7 @@
1833
1887
  .starci-core-fenced-code-block pre {
1834
1888
  max-width: 100%;
1835
1889
  margin: 0;
1836
- padding: 1rem;
1890
+ padding: var(--grammar-inset, 0.75rem);
1837
1891
  overflow-x: auto;
1838
1892
  border: 1px solid var(--border, GrayText);
1839
1893
  border-radius: 0.75rem;
@@ -1855,7 +1909,7 @@
1855
1909
  .starci-core-fenced-code-block {
1856
1910
  width: 100%;
1857
1911
  min-width: 0;
1858
- margin: 0 0 1rem;
1912
+ margin: 0 0 var(--grammar-row-gap, 0.75rem);
1859
1913
  overflow: auto;
1860
1914
  }
1861
1915
 
@@ -1891,14 +1945,14 @@
1891
1945
  [data-grammar-fenced-code-highlight="true"] pre {
1892
1946
  width: max-content;
1893
1947
  min-width: 100%;
1894
- padding: 1rem;
1948
+ padding: var(--grammar-inset, 0.75rem);
1895
1949
  border: 0;
1896
1950
  border-radius: 0;
1897
1951
  background: transparent !important;
1898
1952
  }
1899
1953
 
1900
1954
  .starci-core-markdown-article blockquote {
1901
- padding-inline-start: 1rem;
1955
+ padding-inline-start: var(--grammar-inset, 0.75rem);
1902
1956
  border-inline-start: 3px solid var(--border, GrayText);
1903
1957
  color: var(--muted, GrayText);
1904
1958
  }
@@ -1926,14 +1980,14 @@
1926
1980
 
1927
1981
  .starci-core-markdown-article hr {
1928
1982
  width: 100%;
1929
- margin: 1rem 0;
1983
+ margin: var(--grammar-row-gap, 0.75rem) 0;
1930
1984
  border: 0;
1931
1985
  border-top: 1px solid var(--separator, var(--border, GrayText));
1932
1986
  }
1933
1987
 
1934
1988
  .starci-core-markdown-article :where(th, td) {
1935
1989
  min-width: 8rem;
1936
- padding: 0.625rem 0.75rem;
1990
+ padding: var(--grammar-inset-nested, 0.5rem) var(--grammar-inset, 0.75rem);
1937
1991
  border-bottom: 1px solid var(--separator, var(--border, GrayText));
1938
1992
  text-align: start;
1939
1993
  vertical-align: top;
@@ -2000,7 +2054,7 @@
2000
2054
  min-width: 0;
2001
2055
  max-height: calc(100dvh - var(--starci-core-rail-offset, var(--starci-core-band-offset, 5.5rem)) - 1.5rem);
2002
2056
  flex-direction: column;
2003
- gap: var(--starci-core-rail-gap, 1rem);
2057
+ gap: var(--starci-core-rail-gap, var(--grammar-row-gap, 0.75rem));
2004
2058
  }
2005
2059
 
2006
2060
  .starci-core-rail[data-grammar-rail-mode="sticky"] .starci-core-rail-frame {
@@ -2018,8 +2072,7 @@
2018
2072
 
2019
2073
  /* Grammar-owned content inset, selected by the attribute the branch already emits. */
2020
2074
  .starci-core-rail-body[data-grammar-rail-inset="content"] {
2021
- padding-inline: 0.75rem;
2022
- padding-block: 1.5rem;
2075
+ padding: var(--grammar-inset, 0.75rem);
2023
2076
  }
2024
2077
 
2025
2078
  .starci-core-rail[data-grammar-rail-height="fill"],
@@ -2090,7 +2143,7 @@
2090
2143
  .starci-core-section-header {
2091
2144
  align-items: flex-start;
2092
2145
  flex-direction: column;
2093
- gap: var(--grammar-region-gap, 1.5rem);
2146
+ gap: var(--grammar-region-gap, 2rem);
2094
2147
  }
2095
2148
  }
2096
2149
 
@@ -2366,7 +2419,7 @@
2366
2419
 
2367
2420
  .starci-core-workspace-shell-header {
2368
2421
  min-width: 0;
2369
- margin-block-end: var(--grammar-region-gap, 1.5rem);
2422
+ margin-block-end: var(--grammar-region-gap, 2rem);
2370
2423
  }
2371
2424
 
2372
2425
  .starci-core-workspace-shell-compact-header,
@@ -2394,7 +2447,7 @@
2394
2447
  min-width: 0;
2395
2448
  grid-template-areas: "navigation" "primary" "rail";
2396
2449
  grid-template-columns: minmax(0, 1fr);
2397
- gap: var(--grammar-region-gap, 1.5rem);
2450
+ gap: var(--grammar-region-gap, 2rem);
2398
2451
  }
2399
2452
 
2400
2453
  .starci-core-workspace-shell-layout[data-grammar-workspace-navigation-track="intrinsic"] {
@@ -2509,7 +2562,7 @@
2509
2562
  .starci-core-workspace-shell-primary {
2510
2563
  display: flex;
2511
2564
  flex-direction: column;
2512
- gap: var(--grammar-region-gap, 1.5rem);
2565
+ gap: var(--grammar-region-gap, 2rem);
2513
2566
  outline: none;
2514
2567
  }
2515
2568
 
@@ -2542,7 +2595,7 @@
2542
2595
  block-size: 4rem;
2543
2596
  align-items: center;
2544
2597
  padding-block: 0.5rem;
2545
- padding-inline: var(--grammar-page-inset, 1rem);
2598
+ padding-inline: var(--grammar-page-inset, 0.75rem);
2546
2599
  border-block-end: 1px solid var(--separator, GrayText);
2547
2600
  background: var(--surface, Canvas);
2548
2601
  }
@@ -2582,7 +2635,7 @@
2582
2635
  min-block-size: 4rem;
2583
2636
  align-items: center;
2584
2637
  gap: var(--grammar-inline-gap, 0.5rem);
2585
- padding-inline: var(--grammar-page-inset, 1rem);
2638
+ padding-inline: var(--grammar-page-inset, 0.75rem);
2586
2639
  padding-block: 0.5rem;
2587
2640
  border-block-end: 1px solid var(--separator, var(--starci-core-separator, GrayText));
2588
2641
  background: var(--surface, Canvas);
@@ -2678,8 +2731,8 @@
2678
2731
 
2679
2732
  .starci-core-sidebar[data-collapsed="true"] .starci-core-sidebar-list {
2680
2733
  align-items: center;
2681
- gap: 1rem;
2682
- padding: 0.5rem !important;
2734
+ gap: var(--grammar-section-gap, 1.5rem);
2735
+ padding: var(--grammar-inset, 0.75rem) !important;
2683
2736
  }
2684
2737
 
2685
2738
  .starci-core-sidebar-section {
@@ -2836,9 +2889,9 @@
2836
2889
  */
2837
2890
  .starci-core-pane[data-grammar-pane-inset="content"],
2838
2891
  .starci-core-pane-drawer-scroll[data-grammar-pane-inset="content"] {
2839
- --starci-core-pane-inset-inline: var(--grammar-pane-inset-inline, 1rem);
2892
+ --starci-core-pane-inset-inline: var(--grammar-pane-inset-inline, 0.75rem);
2840
2893
  --starci-core-pane-inset-block-start: var(--grammar-pane-inset-block-start, 0.75rem);
2841
- --starci-core-pane-inset-block-end: var(--starci-core-pane-be, var(--grammar-pane-inset-block-end-outer, 1rem));
2894
+ --starci-core-pane-inset-block-end: var(--starci-core-pane-be, var(--grammar-pane-inset-block-end-outer, 0.75rem));
2842
2895
  }
2843
2896
 
2844
2897
  .starci-core-pane[data-grammar-pane-inset="flush"] {
@@ -2875,7 +2928,7 @@
2875
2928
  }
2876
2929
 
2877
2930
  .starci-core-pane-section[data-grammar-pane-section-gap="inline"] { gap: var(--grammar-inline-gap, 0.5rem); }
2878
- .starci-core-pane-section[data-grammar-pane-section-gap="section"] { gap: var(--grammar-section-gap, 1rem); }
2931
+ .starci-core-pane-section[data-grammar-pane-section-gap="section"] { gap: var(--grammar-section-gap, 1.5rem); }
2879
2932
 
2880
2933
  .starci-core-pane-section[data-grammar-pane-section-grow="true"] {
2881
2934
  min-height: 0;
@@ -2908,7 +2961,7 @@
2908
2961
  }
2909
2962
 
2910
2963
  .starci-core-pane-section[data-grammar-pane-section-gap="inline"] > .starci-core-pane-section-content { gap: var(--grammar-inline-gap, 0.5rem); }
2911
- .starci-core-pane-section[data-grammar-pane-section-gap="section"] > .starci-core-pane-section-content { gap: var(--grammar-section-gap, 1rem); }
2964
+ .starci-core-pane-section[data-grammar-pane-section-gap="section"] > .starci-core-pane-section-content { gap: var(--grammar-section-gap, 1.5rem); }
2912
2965
 
2913
2966
  .starci-core-pane-stack > .starci-core-pane-section:first-child > .starci-core-pane-section-content {
2914
2967
  padding-block-start: var(--starci-core-pane-inset-block-start, 0px);
@@ -2956,7 +3009,7 @@
2956
3009
  flex-wrap: wrap;
2957
3010
  justify-content: flex-end;
2958
3011
  gap: var(--grammar-inline-gap, 0.5rem);
2959
- padding: 0.5rem 1rem;
3012
+ padding: var(--grammar-inset-nested, 0.5rem) var(--grammar-inset, 0.75rem);
2960
3013
  border-bottom: 1px solid var(--separator, var(--starci-core-separator, GrayText));
2961
3014
  }
2962
3015
 
@@ -3124,7 +3177,7 @@
3124
3177
  gap: var(--grammar-inline-gap, 0.5rem);
3125
3178
  border-block-start: 1px solid var(--separator, var(--starci-core-separator, GrayText));
3126
3179
  background: var(--background, var(--starci-core-canvas, Canvas));
3127
- padding: 0.75rem 1rem;
3180
+ padding: var(--grammar-inset, 0.75rem);
3128
3181
  }
3129
3182
  }
3130
3183
 
@@ -3172,7 +3225,7 @@
3172
3225
  width: 100% !important;
3173
3226
  min-width: 0;
3174
3227
  flex-direction: column !important;
3175
- gap: var(--grammar-section-gap, 1rem) !important;
3228
+ gap: var(--grammar-row-gap, 0.75rem) !important;
3176
3229
  padding: 0 !important;
3177
3230
  }
3178
3231
 
@@ -3228,8 +3281,8 @@
3228
3281
  min-width: 0;
3229
3282
  flex-direction: column;
3230
3283
  align-items: center;
3231
- gap: 0.75rem;
3232
- padding: 1rem;
3284
+ gap: var(--grammar-row-gap, 0.75rem);
3285
+ padding: var(--grammar-inset-open, 1.5rem);
3233
3286
  text-align: center;
3234
3287
  }
3235
3288
 
@@ -3254,8 +3307,8 @@
3254
3307
  .starci-core-surface-content > .starci-core-divider-bare:not([data-grammar-divider-orientation="vertical"]) {
3255
3308
  align-self: stretch;
3256
3309
  inline-size: auto !important;
3257
- margin-inline: calc(-1 * var(--grammar-card-padding-inline, 1rem)) !important;
3258
- margin-block: var(--grammar-card-padding-block, 1rem);
3310
+ margin-inline: calc(-1 * var(--grammar-card-padding-inline, 0.75rem)) !important;
3311
+ margin-block: var(--grammar-card-padding-block, 0.75rem);
3259
3312
  }
3260
3313
 
3261
3314
  /* A vertical hairline between touching columns of one joined surface: it fills the row, whatever its height. */
@@ -3269,6 +3322,81 @@
3269
3322
  background-color: var(--background);
3270
3323
  }
3271
3324
 
3325
+ /*
3326
+ * --- Stack, Cluster, Grid: layout named by the relation, the step resolved here. ---
3327
+ *
3328
+ * The app names a gap role (`identity`, `inline`, `row`, `section`, `region`); each resolves to its root token, so
3329
+ * an app writes no spacing value. A cluster's wrapped line is the same set, so its two axes take one role. Peer cards
3330
+ * of one collection stand a section step apart on both axes: wider than the card's own inset (12), so each card
3331
+ * reads as its own unit, never as one box.
3332
+ */
3333
+ .starci-core-stack {
3334
+ display: flex;
3335
+ min-width: 0;
3336
+ flex-direction: column;
3337
+ }
3338
+
3339
+ .starci-core-cluster {
3340
+ display: flex;
3341
+ min-width: 0;
3342
+ flex-flow: row wrap;
3343
+ }
3344
+
3345
+ .starci-core-cluster[data-grammar-wrap="false"] {
3346
+ flex-wrap: nowrap;
3347
+ }
3348
+
3349
+ :is(.starci-core-stack, .starci-core-cluster)[data-grammar-gap="identity"] { gap: var(--grammar-identity-gap, 0.25rem); }
3350
+ :is(.starci-core-stack, .starci-core-cluster)[data-grammar-gap="inline"] { gap: var(--grammar-inline-gap, 0.5rem); }
3351
+ :is(.starci-core-stack, .starci-core-cluster)[data-grammar-gap="row"] { gap: var(--grammar-row-gap, 0.75rem); }
3352
+ :is(.starci-core-stack, .starci-core-cluster)[data-grammar-gap="section"] { gap: var(--grammar-section-gap, 1.5rem); }
3353
+ .starci-core-stack[data-grammar-gap="region"] { gap: var(--grammar-region-gap, 2rem); }
3354
+
3355
+ .starci-core-stack[data-grammar-align="start"] { align-items: flex-start; }
3356
+ .starci-core-stack[data-grammar-align="center"] { align-items: center; }
3357
+ .starci-core-stack[data-grammar-align="end"] { align-items: flex-end; }
3358
+
3359
+ .starci-core-stack[data-grammar-measure="reading"] {
3360
+ width: min(100%, var(--starci-core-reading-measure, 72ch));
3361
+ margin-inline: auto;
3362
+ }
3363
+
3364
+ .starci-core-stack[data-grammar-measure="form"] {
3365
+ width: min(100%, var(--starci-core-form-measure, 30rem));
3366
+ margin-inline: auto;
3367
+ }
3368
+
3369
+ .starci-core-cluster[data-grammar-align="start"] { align-items: flex-start; }
3370
+ .starci-core-cluster[data-grammar-align="center"] { align-items: center; }
3371
+ .starci-core-cluster[data-grammar-align="baseline"] { align-items: baseline; }
3372
+ .starci-core-cluster[data-grammar-align="end"] { align-items: flex-end; }
3373
+ .starci-core-cluster[data-grammar-justify="end"] { justify-content: flex-end; }
3374
+ .starci-core-cluster[data-grammar-justify="between"] { justify-content: space-between; }
3375
+
3376
+ .starci-core-grid[data-grammar-grid-kind="cards"] {
3377
+ --starci-core-grid-gap: var(--grammar-section-gap, 1.5rem);
3378
+ --starci-core-grid-min: 16rem;
3379
+ display: grid;
3380
+ min-width: 0;
3381
+ gap: var(--starci-core-grid-gap);
3382
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--starci-core-grid-min)), 1fr));
3383
+ }
3384
+
3385
+ /* A column cap: each track is at least the share of `n` columns, so a row never holds more than `n` cards. */
3386
+ .starci-core-grid[data-grammar-grid-columns="2"] { --starci-core-grid-share: 2; }
3387
+ .starci-core-grid[data-grammar-grid-columns="3"] { --starci-core-grid-share: 3; }
3388
+ .starci-core-grid[data-grammar-grid-columns="4"] { --starci-core-grid-share: 4; }
3389
+
3390
+ .starci-core-grid:is([data-grammar-grid-columns="2"], [data-grammar-grid-columns="3"], [data-grammar-grid-columns="4"]) {
3391
+ grid-template-columns: repeat(
3392
+ auto-fill,
3393
+ minmax(
3394
+ min(100%, max(var(--starci-core-grid-min), (100% - (var(--starci-core-grid-share) - 1) * var(--starci-core-grid-gap)) / var(--starci-core-grid-share))),
3395
+ 1fr
3396
+ )
3397
+ );
3398
+ }
3399
+
3272
3400
  /* Region, List, ListItem: semantic page structure that draws nothing of its own. */
3273
3401
  .starci-core-region[data-grammar-region-spacing="spaced"] {
3274
3402
  padding-block-end: 2rem;
@@ -3282,7 +3410,7 @@
3282
3410
  }
3283
3411
 
3284
3412
  .starci-core-nav-landmark[data-grammar-nav-layout="bar"] {
3285
- gap: 1rem;
3413
+ gap: var(--grammar-section-gap, 1.5rem);
3286
3414
  }
3287
3415
 
3288
3416
  .starci-core-nav-landmark[data-grammar-nav-layout="scrolling"] {
@@ -3317,7 +3445,7 @@
3317
3445
  display: flex;
3318
3446
  min-width: 0;
3319
3447
  flex-direction: column;
3320
- padding: 0.75rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
3448
+ padding: var(--grammar-inset, 0.75rem) var(--grammar-inset, 0.75rem) calc(var(--grammar-inset, 0.75rem) + env(safe-area-inset-bottom, 0px));
3321
3449
  border-block-start: 1px solid var(--separator, var(--starci-core-separator, CanvasText));
3322
3450
  background: var(--surface, Canvas);
3323
3451
  color: var(--surface-foreground, CanvasText);
@@ -3640,7 +3768,7 @@
3640
3768
 
3641
3769
  .starci-core-input-actions .starci-core-input-reveal {
3642
3770
  min-height: 1.75rem;
3643
- padding-inline: 0.375rem;
3771
+ padding-inline: var(--grammar-identity-gap, 0.25rem);
3644
3772
  border-radius: var(--radius-sm, calc(var(--radius, 0.5rem) * 0.5));
3645
3773
  }
3646
3774
 
@@ -4021,7 +4149,7 @@
4021
4149
  .starci-core-status-dot-mark[data-tone="danger"] { --starci-core-status-dot-color: var(--danger, CanvasText); }
4022
4150
 
4023
4151
  .starci-core-status-dot-chip > .starci-core-status-dot-mark {
4024
- margin-inline-end: 0.125rem;
4152
+ margin-inline-end: var(--grammar-identity-gap, 0.25rem);
4025
4153
  }
4026
4154
 
4027
4155
  .starci-core-status-dot-label {
@@ -4076,7 +4204,7 @@
4076
4204
  .starci-core-badge-muted {
4077
4205
  display: inline-flex;
4078
4206
  align-items: center;
4079
- gap: 0.125rem;
4207
+ gap: var(--grammar-identity-gap, 0.25rem);
4080
4208
  color: var(--muted, GrayText);
4081
4209
  }
4082
4210
 
@@ -4223,7 +4351,7 @@
4223
4351
  .starci-core-chat-bubble-actions {
4224
4352
  display: flex;
4225
4353
  align-items: center;
4226
- gap: 0.125rem;
4354
+ gap: var(--grammar-identity-gap, 0.25rem);
4227
4355
  opacity: 0;
4228
4356
  transition: opacity var(--starci-core-motion-duration, 150ms) cubic-bezier(0.4, 0, 0.2, 1);
4229
4357
  }
@@ -4234,7 +4362,7 @@
4234
4362
  z-index: 1;
4235
4363
  inset-block-start: 50%;
4236
4364
  transform: translateY(-50%);
4237
- padding: 0.125rem;
4365
+ padding: var(--grammar-identity-gap, 0.25rem);
4238
4366
  border: 1px solid var(--border, GrayText);
4239
4367
  border-radius: 0.75rem;
4240
4368
  background: var(--surface, Canvas);
@@ -4268,7 +4396,7 @@
4268
4396
  /* Loading bubble (knowledge STATE-8): the face on its side with two Skeleton lines; a thread alternates sides. */
4269
4397
  .starci-core-chat-bubble-skeleton-body { inline-size: min(18rem, 70vw); white-space: normal; }
4270
4398
  .starci-core-chat-bubble-skeleton-body .starci-core-skeleton { --starci-core-skeleton-line: 0.875rem; }
4271
- .starci-core-chat-bubble-thread { display: flex; min-width: 0; flex-direction: column; gap: 1rem; }
4399
+ .starci-core-chat-bubble-thread { display: flex; min-width: 0; flex-direction: column; gap: var(--grammar-row-gap, 0.75rem); }
4272
4400
 
4273
4401
  @media (forced-colors: active) {
4274
4402
  .starci-core-chat-bubble-body { border: 1px solid CanvasText; }
@@ -4313,7 +4441,7 @@
4313
4441
  display: flex;
4314
4442
  min-width: 0;
4315
4443
  flex-direction: column;
4316
- gap: 0.125rem;
4444
+ gap: var(--grammar-identity-gap, 0.25rem);
4317
4445
  padding: 0.5rem 0.75rem;
4318
4446
  border-radius: var(--radius, 0.5rem);
4319
4447
  cursor: pointer;