@gjermundgaraba-designs/pixel-paper 0.22.2 → 0.24.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 (176) hide show
  1. package/DESIGN.md +18 -17
  2. package/dist/src/adapters/mermaid.d.ts.map +1 -1
  3. package/dist/src/adapters/mermaid.js +0 -24
  4. package/dist/src/announcer/announcer.d.ts.map +1 -1
  5. package/dist/src/announcer/announcer.js +12 -12
  6. package/dist/src/board/board.d.ts +0 -10
  7. package/dist/src/board/board.d.ts.map +1 -1
  8. package/dist/src/board/board.js +36 -64
  9. package/dist/src/board/index.d.ts +2 -1
  10. package/dist/src/board/index.d.ts.map +1 -1
  11. package/dist/src/board/index.js +2 -1
  12. package/dist/src/button/button.d.ts +1 -1
  13. package/dist/src/button/button.d.ts.map +1 -1
  14. package/dist/src/commandPalette/commandPalette.d.ts.map +1 -1
  15. package/dist/src/commandPalette/commandPalette.js +78 -83
  16. package/dist/src/commandPalette/keys.d.ts +2 -2
  17. package/dist/src/commandPalette/keys.d.ts.map +1 -1
  18. package/dist/src/commandPalette/keys.js +2 -4
  19. package/dist/src/commandPalette/match.d.ts.map +1 -1
  20. package/dist/src/commandPalette/match.js +2 -2
  21. package/dist/src/confirmDialog/confirmDialog.d.ts.map +1 -1
  22. package/dist/src/confirmDialog/confirmDialog.js +1 -2
  23. package/dist/src/copyButton/copyButton.d.ts +0 -5
  24. package/dist/src/copyButton/copyButton.d.ts.map +1 -1
  25. package/dist/src/copyButton/copyButton.js +2 -2
  26. package/dist/src/crumbs/crumbs.d.ts +0 -2
  27. package/dist/src/crumbs/crumbs.d.ts.map +1 -1
  28. package/dist/src/crumbs/crumbs.js +2 -2
  29. package/dist/src/dialog/dialog.d.ts +2 -0
  30. package/dist/src/dialog/dialog.d.ts.map +1 -1
  31. package/dist/src/dialog/dialog.js +3 -2
  32. package/dist/src/drag/drag.d.ts +28 -0
  33. package/dist/src/drag/drag.d.ts.map +1 -1
  34. package/dist/src/drag/drag.js +39 -17
  35. package/dist/src/editableTitle/editableTitle.d.ts +4 -4
  36. package/dist/src/field/field.d.ts +7 -1
  37. package/dist/src/field/field.d.ts.map +1 -1
  38. package/dist/src/field/field.js +14 -6
  39. package/dist/src/fieldset/fieldset.d.ts.map +1 -1
  40. package/dist/src/fieldset/fieldset.js +2 -4
  41. package/dist/src/fileTree/fileTree.d.ts.map +1 -1
  42. package/dist/src/fileTree/fileTree.js +16 -16
  43. package/dist/src/iconButton/iconButton.d.ts +6 -1
  44. package/dist/src/iconButton/iconButton.d.ts.map +1 -1
  45. package/dist/src/iconButton/iconButton.js +7 -2
  46. package/dist/src/inlineInput/inlineInput.d.ts +4 -0
  47. package/dist/src/inlineInput/inlineInput.d.ts.map +1 -1
  48. package/dist/src/inlineInput/inlineInput.js +9 -6
  49. package/dist/src/keyHelp/index.d.ts +1 -1
  50. package/dist/src/keyHelp/index.d.ts.map +1 -1
  51. package/dist/src/keyHelp/index.js +1 -1
  52. package/dist/src/keyHelp/keyHelp.d.ts +1 -3
  53. package/dist/src/keyHelp/keyHelp.d.ts.map +1 -1
  54. package/dist/src/keyHelp/keyHelp.js +3 -6
  55. package/dist/src/keyHint/keyLabel.d.ts +2 -0
  56. package/dist/src/keyHint/keyLabel.d.ts.map +1 -1
  57. package/dist/src/keyHint/keyLabel.js +3 -2
  58. package/dist/src/lineDiff/diff.d.ts +6 -3
  59. package/dist/src/lineDiff/diff.d.ts.map +1 -1
  60. package/dist/src/lineDiff/diff.js +40 -28
  61. package/dist/src/lineDiff/patch.d.ts.map +1 -1
  62. package/dist/src/lineDiff/patch.js +18 -13
  63. package/dist/src/linkState/linkState.d.ts.map +1 -1
  64. package/dist/src/linkState/linkState.js +1 -7
  65. package/dist/src/menu/slip.js +2 -2
  66. package/dist/src/meter/meter.d.ts.map +1 -1
  67. package/dist/src/meter/meter.js +22 -17
  68. package/dist/src/notice/notice.d.ts +2 -0
  69. package/dist/src/notice/notice.d.ts.map +1 -1
  70. package/dist/src/notice/notice.js +2 -1
  71. package/dist/src/panel/panel.d.ts +3 -0
  72. package/dist/src/panel/panel.d.ts.map +1 -1
  73. package/dist/src/panel/panel.js +2 -1
  74. package/dist/src/passwordField/passwordField.d.ts.map +1 -1
  75. package/dist/src/passwordField/passwordField.js +3 -7
  76. package/dist/src/rail/index.d.ts +1 -1
  77. package/dist/src/rail/index.d.ts.map +1 -1
  78. package/dist/src/rail/index.js +1 -1
  79. package/dist/src/rail/rail.d.ts +95 -20
  80. package/dist/src/rail/rail.d.ts.map +1 -1
  81. package/dist/src/rail/rail.js +103 -46
  82. package/dist/src/reel/layout.d.ts +9 -5
  83. package/dist/src/reel/layout.d.ts.map +1 -1
  84. package/dist/src/reel/layout.js +11 -5
  85. package/dist/src/reel/reel.d.ts.map +1 -1
  86. package/dist/src/reel/reel.js +122 -68
  87. package/dist/src/scheme/scheme.d.ts +1 -1
  88. package/dist/src/scheme/scheme.d.ts.map +1 -1
  89. package/dist/src/segmented/segmented.d.ts +0 -3
  90. package/dist/src/segmented/segmented.d.ts.map +1 -1
  91. package/dist/src/segmented/segmented.js +1 -6
  92. package/dist/src/selectField/selectField.d.ts.map +1 -1
  93. package/dist/src/selectField/selectField.js +3 -10
  94. package/dist/src/sortable/index.d.ts +1 -1
  95. package/dist/src/sortable/index.d.ts.map +1 -1
  96. package/dist/src/sortable/index.js +1 -1
  97. package/dist/src/sortable/sortable.d.ts +39 -40
  98. package/dist/src/sortable/sortable.d.ts.map +1 -1
  99. package/dist/src/sortable/sortable.js +14 -31
  100. package/dist/src/stack/stack.d.ts +1 -1
  101. package/dist/src/stack/stack.d.ts.map +1 -1
  102. package/dist/src/stack/stack.js +1 -1
  103. package/dist/src/tabs/tabs.d.ts +1 -1
  104. package/dist/src/tabs/tabs.d.ts.map +1 -1
  105. package/dist/src/tabs/tabs.js +1 -1
  106. package/dist/src/textareaField/textareaField.d.ts.map +1 -1
  107. package/dist/src/textareaField/textareaField.js +3 -7
  108. package/dist/src/time/time.d.ts.map +1 -1
  109. package/dist/src/time/time.js +4 -2
  110. package/dist/src/tips/index.d.ts +1 -1
  111. package/dist/src/tips/index.d.ts.map +1 -1
  112. package/dist/src/tips/tips.d.ts +30 -1
  113. package/dist/src/tips/tips.d.ts.map +1 -1
  114. package/dist/src/tips/tips.js +53 -31
  115. package/dist/src/toast/index.d.ts +1 -1
  116. package/dist/src/toast/index.d.ts.map +1 -1
  117. package/dist/src/toast/toast.d.ts +5 -5
  118. package/dist/src/toast/toast.d.ts.map +1 -1
  119. package/dist/src/toast/toast.js +1 -6
  120. package/dist/src/toolbar/toolbar.d.ts +0 -3
  121. package/dist/src/toolbar/toolbar.d.ts.map +1 -1
  122. package/dist/src/toolbar/toolbar.js +1 -2
  123. package/package.json +1 -1
  124. package/src/adapters/mermaid.ts +0 -24
  125. package/src/announcer/announcer.ts +13 -17
  126. package/src/board/board.ts +32 -80
  127. package/src/board/index.ts +1 -1
  128. package/src/button/button.ts +1 -1
  129. package/src/commandPalette/commandPalette.ts +21 -38
  130. package/src/commandPalette/keys.ts +2 -4
  131. package/src/commandPalette/match.ts +3 -3
  132. package/src/confirmDialog/confirmDialog.ts +5 -3
  133. package/src/copyButton/copyButton.ts +2 -5
  134. package/src/crumbs/crumbs.ts +2 -4
  135. package/src/dialog/dialog.ts +3 -2
  136. package/src/drag/drag.ts +54 -5
  137. package/src/field/field.ts +29 -7
  138. package/src/fieldset/fieldset.ts +2 -4
  139. package/src/fileTree/fileTree.ts +10 -12
  140. package/src/iconButton/iconButton.ts +19 -2
  141. package/src/inlineInput/inlineInput.ts +11 -2
  142. package/src/keyHelp/index.ts +0 -1
  143. package/src/keyHelp/keyHelp.ts +3 -9
  144. package/src/keyHint/keyLabel.ts +5 -2
  145. package/src/lineDiff/diff.ts +70 -54
  146. package/src/lineDiff/patch.ts +27 -14
  147. package/src/linkState/linkState.ts +1 -8
  148. package/src/menu/slip.ts +2 -2
  149. package/src/meter/meter.ts +25 -15
  150. package/src/notice/notice.ts +2 -1
  151. package/src/panel/panel.ts +5 -0
  152. package/src/passwordField/passwordField.ts +3 -7
  153. package/src/pixel-paper.css +200 -134
  154. package/src/rail/index.ts +2 -0
  155. package/src/rail/rail.ts +124 -44
  156. package/src/reel/layout.ts +14 -7
  157. package/src/reel/reel.ts +132 -63
  158. package/src/scheme/scheme.ts +1 -1
  159. package/src/segmented/segmented.ts +1 -9
  160. package/src/selectField/selectField.ts +3 -10
  161. package/src/sortable/index.ts +0 -1
  162. package/src/sortable/sortable.ts +35 -54
  163. package/src/stack/stack.ts +1 -1
  164. package/src/tabs/tabs.ts +1 -1
  165. package/src/textareaField/textareaField.ts +3 -7
  166. package/src/time/time.ts +6 -7
  167. package/src/tips/index.ts +1 -1
  168. package/src/tips/tips.ts +71 -35
  169. package/src/toast/index.ts +1 -1
  170. package/src/toast/toast.ts +2 -8
  171. package/src/tokens.css +7 -0
  172. package/src/toolbar/toolbar.ts +0 -5
  173. package/dist/src/inlineInput/inline.d.ts +0 -6
  174. package/dist/src/inlineInput/inline.d.ts.map +0 -1
  175. package/dist/src/inlineInput/inline.js +0 -7
  176. package/src/inlineInput/inline.ts +0 -13
@@ -13,11 +13,17 @@
13
13
 
14
14
  /* anchors land 16px clear of the sticky top bar, at the height TopBar measures it to be
15
15
  however it wraps; without Foldkit, at one line's height. A status bar along the bottom is
16
- kept clear the same way: the page ends above it, and so does a scrolled-to anchor */
16
+ kept clear the same way: the page ends above it, and so does a scrolled-to anchor. The
17
+ measured heights are written inline on <html>, over these */
18
+ :root {
19
+ --topbar-h: 48px;
20
+ --statusbar-h: 0px;
21
+ }
22
+
17
23
  html {
18
24
  height: 100%;
19
- scroll-padding-top: calc(var(--topbar-h, 48px) + 16px);
20
- scroll-padding-bottom: var(--statusbar-h, 0px);
25
+ scroll-padding-top: calc(var(--topbar-h) + 16px);
26
+ scroll-padding-bottom: var(--statusbar-h);
21
27
  }
22
28
 
23
29
  :root:has(footer.statusbar) {
@@ -26,7 +32,7 @@ html {
26
32
 
27
33
  body {
28
34
  min-height: 100%;
29
- padding-bottom: var(--statusbar-h, 0px);
35
+ padding-bottom: var(--statusbar-h);
30
36
  font-family: var(--font-body);
31
37
  font-size: var(--type-body);
32
38
  line-height: 1.45;
@@ -40,10 +46,6 @@ fieldset {
40
46
  min-width: 0;
41
47
  }
42
48
 
43
- legend {
44
- padding: 0;
45
- }
46
-
47
49
  ::selection {
48
50
  background: var(--ink);
49
51
  color: var(--paper);
@@ -93,7 +95,6 @@ kbd {
93
95
  position: absolute;
94
96
  width: 1px;
95
97
  height: 1px;
96
- padding: 0;
97
98
  margin: -1px;
98
99
  overflow: hidden;
99
100
  clip-path: inset(50%);
@@ -129,8 +130,8 @@ kbd {
129
130
  keeps its look and takes the pointer over an invisible 24px square centred on it */
130
131
  :is(
131
132
  .nav.tabs button,
132
- .switch > :is(a, button),
133
- :is(button, a, label).fchip,
133
+ .switch > button,
134
+ :is(button, label).fchip,
134
135
  button.glyph,
135
136
  button.mark,
136
137
  button.tag:has(> span),
@@ -143,8 +144,8 @@ kbd {
143
144
 
144
145
  :is(
145
146
  .nav.tabs button,
146
- .switch > :is(a, button),
147
- :is(button, a, label).fchip,
147
+ .switch > button,
148
+ :is(button, label).fchip,
148
149
  button.glyph,
149
150
  button.mark,
150
151
  button.tag:has(> span),
@@ -340,7 +341,6 @@ button.tag > span {
340
341
  font-size: var(--type-wordmark);
341
342
  font-weight: 400;
342
343
  letter-spacing: -0.02em;
343
- margin: 0;
344
344
  color: inherit;
345
345
  text-decoration: none;
346
346
  white-space: nowrap;
@@ -378,8 +378,8 @@ button.tag > span {
378
378
  flex: 1;
379
379
  }
380
380
 
381
- /* the right-hand tools wrap as one group, never one control per line */
382
- /* a bar of tools wider than the window wraps onto lines of its own, at the right */
381
+ /* the right-hand tools wrap as one group, never one control per line; a group wider than the
382
+ window wraps onto lines of its own, at the right */
383
383
  .topbar-tools {
384
384
  display: flex;
385
385
  flex-wrap: wrap;
@@ -456,7 +456,6 @@ a.textbtn {
456
456
  }
457
457
 
458
458
  /* tabs at the top of a flush panel sit inside its padding */
459
- .panel > .nav.tabs,
460
459
  .panel > .tabbed > .nav.tabs {
461
460
  margin: var(--pad) var(--pad) 0;
462
461
  }
@@ -498,7 +497,6 @@ a.textbtn {
498
497
  color: var(--on-head);
499
498
  }
500
499
 
501
- .nav.tabs a,
502
500
  .nav.tabs button {
503
501
  padding: 4px 12px;
504
502
  font-size: var(--type-state);
@@ -607,7 +605,7 @@ a.textbtn {
607
605
 
608
606
  .places li:has(> [aria-current]) :is(.place-count, .iconbtn.quiet) {
609
607
  color: inherit;
610
- opacity: 0.75;
608
+ opacity: var(--fade-on-ink);
611
609
  }
612
610
 
613
611
  .places li:has(> [aria-current]) :focus-visible {
@@ -798,8 +796,6 @@ a.textbtn {
798
796
  .menu {
799
797
  position: absolute;
800
798
  z-index: 200;
801
- margin: 0;
802
- padding: 0;
803
799
  min-width: 148px;
804
800
  max-width: calc(100vw - 24px);
805
801
  color: var(--ink);
@@ -875,7 +871,7 @@ a.textbtn {
875
871
 
876
872
  .menu :is([aria-current="page"], [role="menuitemradio"][aria-checked="true"]) .key-hint {
877
873
  color: inherit;
878
- opacity: 0.75;
874
+ opacity: var(--fade-on-ink);
879
875
  }
880
876
 
881
877
  .menu .menu-check {
@@ -952,7 +948,7 @@ a.textbtn {
952
948
  margin-left: auto;
953
949
  font-size: var(--type-state);
954
950
  color: inherit;
955
- opacity: 0.75;
951
+ opacity: var(--fade-on-ink);
956
952
  }
957
953
 
958
954
  .panel-body {
@@ -983,6 +979,19 @@ a.textbtn {
983
979
  flex: 1 1 100%;
984
980
  }
985
981
 
982
+ /* the shelf: a strip on the head tint under the bar, for a field that picks what the body
983
+ shows */
984
+ .panel-shelf {
985
+ padding: 10px 12px 12px;
986
+ background: var(--head);
987
+ border-bottom: var(--hair) solid var(--rule);
988
+ }
989
+
990
+ /* on the head tint a field's label takes on-head: muted misses AA there */
991
+ .panel-shelf :is(.field > label:not(.choice), .field-label) {
992
+ color: var(--on-head);
993
+ }
994
+
986
995
  /* ---------- the panel's title-bar lead and actions ---------- */
987
996
 
988
997
  /* small buttons and icon buttons at the bar's right end, and an icon button before the
@@ -1046,14 +1055,12 @@ a.textbtn {
1046
1055
  color: var(--paper);
1047
1056
  background: var(--ink);
1048
1057
  border-color: var(--paper);
1049
- opacity: 0.6;
1058
+ opacity: var(--fade-held);
1050
1059
  }
1051
1060
 
1052
1061
  /* a quiet icon button prints in paper, and a hover cannot darken it to the ink of the bar */
1053
1062
  .panel-lead .iconbtn.quiet,
1054
- .panel-acts .iconbtn.quiet,
1055
- .panel-lead .iconbtn.quiet:hover,
1056
- .panel-acts .iconbtn.quiet:hover {
1063
+ .panel-acts .iconbtn.quiet {
1057
1064
  color: inherit;
1058
1065
  }
1059
1066
 
@@ -1087,7 +1094,6 @@ a.textbtn {
1087
1094
  flex: none;
1088
1095
  }
1089
1096
 
1090
- .switch a,
1091
1097
  .switch button {
1092
1098
  width: 26px;
1093
1099
  height: 22px;
@@ -1100,12 +1106,11 @@ a.textbtn {
1100
1106
  cursor: pointer;
1101
1107
  }
1102
1108
 
1103
- .switch > :is(a, button) + :is(a, button) {
1109
+ .switch > button + button {
1104
1110
  border-left: var(--line) solid var(--ink);
1105
1111
  }
1106
1112
 
1107
- .switch [aria-pressed="true"],
1108
- .switch [aria-current="page"] {
1113
+ .switch [aria-pressed="true"] {
1109
1114
  background: var(--ink);
1110
1115
  color: var(--paper);
1111
1116
  }
@@ -1159,11 +1164,6 @@ button.fchip:active {
1159
1164
  color: inherit;
1160
1165
  }
1161
1166
 
1162
- a.fchip {
1163
- cursor: pointer;
1164
- text-decoration: none;
1165
- }
1166
-
1167
1167
  .fchip.query {
1168
1168
  cursor: text;
1169
1169
  isolation: isolate;
@@ -1407,12 +1407,6 @@ button.glyph {
1407
1407
  margin: -4px;
1408
1408
  }
1409
1409
 
1410
- /* an inline edit in a row shows its focus as its caret and its rule, thickened below, not a
1411
- ring */
1412
- .row .grow input.inline-input:focus-visible {
1413
- outline: none;
1414
- }
1415
-
1416
1410
  /* the title opens the record; the pencil renames */
1417
1411
  .row .title {
1418
1412
  font: inherit;
@@ -1510,10 +1504,13 @@ button.glyph {
1510
1504
  outline-offset: -4px;
1511
1505
  }
1512
1506
 
1513
- /* the row you are on (its link is aria-current) prints inverted, as a place and a board's
1514
- cursor card do: hover adds nothing, a dot's border takes the paper, what prints muted on
1515
- paper prints in paper at 0.75, and lateness takes a red slip */
1516
- .row.linked:has(.grow a[aria-current]) {
1507
+ /* the row you are on (its link is aria-current) and a board's cursor card print inverted, as
1508
+ a place does and as the system marks the one current thing: hover adds nothing, what prints
1509
+ muted on paper prints in paper at --fade-on-ink, as a title bar's meta does, chips, marks
1510
+ and buttons keep their own fills, and a ring inside prints in paper. Each selector is
1511
+ written out, not joined in :is(), so each keeps its own specificity */
1512
+ .row.linked:has(.grow a[aria-current]),
1513
+ .board-card[aria-current="true"] {
1517
1514
  background-color: var(--ink);
1518
1515
  color: var(--paper);
1519
1516
  }
@@ -1522,16 +1519,20 @@ button.glyph {
1522
1519
  border-color: var(--paper);
1523
1520
  }
1524
1521
 
1525
- .row.linked:has(.grow a[aria-current]) :is(.glyph, .age, .due, .tag, .done-title, .iconbtn.quiet) {
1522
+ .row.linked:has(.grow a[aria-current]) :is(.glyph, .age, .due, .tag, .done-title, .iconbtn.quiet),
1523
+ .board-card[aria-current="true"] :is(.glyph, .age, .due, .tag, .done-title, .iconbtn.quiet) {
1526
1524
  color: inherit;
1527
- opacity: 0.75;
1525
+ opacity: var(--fade-on-ink);
1528
1526
  }
1529
1527
 
1530
- .row.linked:has(.grow a[aria-current]) .tag {
1528
+ .row.linked:has(.grow a[aria-current]) .tag,
1529
+ .board-card[aria-current="true"] .tag {
1531
1530
  border-color: currentColor;
1532
1531
  }
1533
1532
 
1534
- .row.linked:has(.grow a[aria-current]) :is(.due.late, .age.stale) {
1533
+ /* lateness cannot be red on ink: it takes a red slip, drawn by a spread so nothing moves */
1534
+ .row.linked:has(.grow a[aria-current]) :is(.due.late, .age.stale),
1535
+ .board-card[aria-current="true"] :is(.due.late, .age.stale) {
1535
1536
  opacity: 1;
1536
1537
  background: var(--red);
1537
1538
  color: var(--on-red);
@@ -1539,7 +1540,8 @@ button.glyph {
1539
1540
  }
1540
1541
 
1541
1542
  .row.linked:has(.grow a[aria-current]) :focus-visible,
1542
- .row.linked:has(.grow a[aria-current]:focus-visible) {
1543
+ .row.linked:has(.grow a[aria-current]:focus-visible),
1544
+ .board-card[aria-current="true"] :focus-visible {
1543
1545
  outline-color: var(--paper);
1544
1546
  }
1545
1547
 
@@ -1566,35 +1568,6 @@ button.glyph {
1566
1568
  opacity: 1;
1567
1569
  }
1568
1570
 
1569
- /* a board's cursor card is inverted, as the system marks the one current thing. What prints
1570
- muted on paper prints in paper at 0.75, as a title bar's meta does; chips, marks and buttons
1571
- keep their own fills; a ring inside it prints in paper. Hover adds nothing to it */
1572
- .board-card[aria-current="true"] {
1573
- background-color: var(--ink);
1574
- color: var(--paper);
1575
- }
1576
-
1577
- .board-card[aria-current="true"] :is(.glyph, .age, .due, .tag, .done-title, .iconbtn.quiet) {
1578
- color: inherit;
1579
- opacity: 0.75;
1580
- }
1581
-
1582
- .board-card[aria-current="true"] .tag {
1583
- border-color: currentColor;
1584
- }
1585
-
1586
- /* lateness cannot be red on ink: it takes a red slip, drawn by a spread so nothing moves */
1587
- .board-card[aria-current="true"] :is(.due.late, .age.stale) {
1588
- opacity: 1;
1589
- background: var(--red);
1590
- color: var(--on-red);
1591
- box-shadow: 0 0 0 3px var(--red);
1592
- }
1593
-
1594
- .board-card[aria-current="true"] :focus-visible {
1595
- outline-color: var(--paper);
1596
- }
1597
-
1598
1571
  /* a phone has no room for the hover tools; the detail card carries every edit. Titles
1599
1572
  wrap to a second line instead of clipping to a few characters beside the chips */
1600
1573
  @media (max-width: 600px) {
@@ -1747,10 +1720,11 @@ input.inline-input[aria-invalid="true"] {
1747
1720
  border-bottom-color: var(--red);
1748
1721
  }
1749
1722
 
1750
- /* in a row, which takes its ring, focus doubles the rule to 2px, as a field's baseline does;
1751
- drawn inside the box, so the row keeps its height, and in the rule's own colour, so a
1752
- refused edit stays red */
1723
+ /* in a row, focus shows as the caret and the rule, not a ring: the rule doubles to 2px, as a
1724
+ field's baseline does, drawn inside the box, so the row keeps its height, and in the rule's
1725
+ own colour, so a refused edit stays red */
1753
1726
  .row .grow input.inline-input:focus-visible {
1727
+ outline: none;
1754
1728
  box-shadow: inset 0 -1px 0 var(--ink);
1755
1729
  }
1756
1730
 
@@ -2081,7 +2055,6 @@ textarea::-webkit-resizer {
2081
2055
  font-size: var(--type-control);
2082
2056
  }
2083
2057
 
2084
- .title-edit,
2085
2058
  input.inline-input.title-edit {
2086
2059
  font-size: var(--type-title);
2087
2060
  font-weight: 600;
@@ -2292,12 +2265,6 @@ select[aria-invalid="true"] {
2292
2265
  margin-left: 8px;
2293
2266
  }
2294
2267
 
2295
- .table .chips {
2296
- display: inline-flex;
2297
- gap: 6px;
2298
- flex-wrap: wrap;
2299
- }
2300
-
2301
2268
  /* a stacked table: on a phone each row becomes a block of label and value lines, so a
2302
2269
  pinned action column never slices through what the row says */
2303
2270
  @media (max-width: 600px) {
@@ -2719,15 +2686,10 @@ pre.code-surface {
2719
2686
  element of its own (.veil-backdrop) under the pad; the pad lets a press through to it
2720
2687
  everywhere but on the card it holds, and a press on the veil closes the dialog. */
2721
2688
  dialog.veil {
2722
- margin: 0;
2723
2689
  color: inherit;
2724
2690
  overflow-y: auto;
2725
2691
  }
2726
2692
 
2727
- dialog.veil[open] {
2728
- display: block;
2729
- }
2730
-
2731
2693
  dialog.veil:focus {
2732
2694
  outline: none;
2733
2695
  }
@@ -2819,12 +2781,12 @@ dialog.veil:focus {
2819
2781
  .card-tb .meta {
2820
2782
  font-size: var(--type-state);
2821
2783
  color: inherit;
2822
- opacity: 0.75;
2784
+ opacity: var(--fade-on-ink);
2823
2785
  }
2824
2786
 
2825
2787
  /* a held icon button fades on the bar, as a held button in a panel's title bar does */
2826
2788
  :is(.card-tb, .panel-tb) .iconbtn[aria-disabled="true"] {
2827
- opacity: 0.6;
2789
+ opacity: var(--fade-held);
2828
2790
  cursor: default;
2829
2791
  }
2830
2792
 
@@ -3066,7 +3028,7 @@ dialog.veil:focus {
3066
3028
  .palette-row[aria-selected="true"] .hint,
3067
3029
  .palette-row[aria-selected="true"] .tag {
3068
3030
  color: inherit;
3069
- opacity: 0.75;
3031
+ opacity: var(--fade-on-ink);
3070
3032
  }
3071
3033
 
3072
3034
  .palette-row[aria-selected="true"] .tag {
@@ -3130,7 +3092,6 @@ dialog.veil:focus {
3130
3092
  }
3131
3093
 
3132
3094
  .empty-title {
3133
- margin: 0;
3134
3095
  font-family: var(--font-px);
3135
3096
  font-size: var(--type-control);
3136
3097
  text-transform: uppercase;
@@ -3151,7 +3112,7 @@ dialog.veil:focus {
3151
3112
 
3152
3113
  .banner {
3153
3114
  position: fixed;
3154
- bottom: calc(var(--statusbar-h, 0px) + 16px);
3115
+ bottom: calc(var(--statusbar-h) + 16px);
3155
3116
  left: 50%;
3156
3117
  transform: translateX(-50%);
3157
3118
  z-index: 150;
@@ -3408,7 +3369,7 @@ dialog.veil:focus {
3408
3369
  }
3409
3370
 
3410
3371
  .board-card.drag-dim {
3411
- opacity: 0.4;
3372
+ opacity: var(--fade-dragged);
3412
3373
  }
3413
3374
 
3414
3375
  /* focus on the title rings the whole slip, outside its own border */
@@ -3501,7 +3462,7 @@ dialog.veil:focus {
3501
3462
  }
3502
3463
 
3503
3464
  .sortable-item.drag-dim {
3504
- opacity: 0.4;
3465
+ opacity: var(--fade-dragged);
3505
3466
  }
3506
3467
 
3507
3468
  /* where a pointer would drop the held item: a 2px dashed ink line beside the item it lands
@@ -4880,6 +4841,16 @@ dialog.veil:focus {
4880
4841
  overflow: visible;
4881
4842
  }
4882
4843
 
4844
+ /* the key that does the same as the control, after its words, as a button prints it */
4845
+ .tip .key-hint {
4846
+ margin-left: 6px;
4847
+ font-family: var(--font-px);
4848
+ font-size: var(--type-label);
4849
+ text-transform: none;
4850
+ letter-spacing: 0;
4851
+ opacity: var(--fade-on-ink);
4852
+ }
4853
+
4883
4854
  /* ---------- toolbars: one strip of tools, one stop for Tab ---------- */
4884
4855
 
4885
4856
  /* the rules between tools are the strip's ink showing through a 2px gap */
@@ -5064,7 +5035,6 @@ dialog.veil:focus {
5064
5035
  display: flex;
5065
5036
  flex-wrap: wrap;
5066
5037
  gap: 4px 12px;
5067
- margin: 0;
5068
5038
  }
5069
5039
 
5070
5040
  .statusbar-keys .key-hint {
@@ -5075,25 +5045,34 @@ dialog.veil:focus {
5075
5045
  /* ---------- the rail: a column of panels beside the deck, a drawer on a phone ---------- */
5076
5046
 
5077
5047
  /* one element in two places: at rest, fixed down the left edge from the top bar's lower
5078
- edge (as the stage hangs) and scrolling itself; on a phone the same element opens as a
5079
- popover drawer. --rail is the reader's width when they gave one: the view sets it on
5080
- .railed, so the page's padding and the rail's width follow it together */
5048
+ edge (as the stage hangs); on a phone the same element opens as a popover drawer. The reader's width, when they gave one, is --railed-width, which the view
5049
+ sets on .railed, so the page's padding and the rail's width follow it together; without one,
5050
+ --rail. It is not inherited: each box it sizes takes it from .railed by name, so a width that
5051
+ changes under a dragged splitter restyles those four and none of the rows inside them */
5052
+ @property --railed-width {
5053
+ syntax: "*";
5054
+ inherits: false;
5055
+ }
5056
+
5081
5057
  .railed {
5082
- padding-left: var(--rail);
5058
+ padding-left: var(--railed-width, var(--rail));
5059
+ }
5060
+
5061
+ .railed > :is(.rail, .rail-resize, .bench) {
5062
+ --railed-width: inherit;
5083
5063
  }
5084
5064
 
5085
5065
  .rail[popover] {
5086
5066
  position: fixed;
5087
5067
  inset: auto;
5088
5068
  top: anchor(--topbar bottom, 0px);
5089
- bottom: var(--statusbar-h, 0px);
5069
+ bottom: var(--statusbar-h);
5090
5070
  left: 0;
5091
- display: grid;
5092
- align-content: start;
5071
+ display: flex;
5072
+ flex-direction: column;
5093
5073
  gap: var(--gap);
5094
- width: var(--rail);
5074
+ width: var(--railed-width, var(--rail));
5095
5075
  height: auto;
5096
- margin: 0;
5097
5076
  padding: var(--gap) 10px var(--gap) 20px;
5098
5077
  border: 0;
5099
5078
  background: none;
@@ -5102,7 +5081,43 @@ dialog.veil:focus {
5102
5081
  }
5103
5082
 
5104
5083
  .rail > * {
5084
+ flex: none;
5085
+ min-width: 0;
5086
+ }
5087
+
5088
+ /* the rail's top stays put: what comes before its last panel keeps its height, and the last
5089
+ panel takes the room left, at most its own height, its bar, shelf and foot staying while
5090
+ its body scrolls (the padded body, or a flush body's list). The rail scrolls as a whole
5091
+ only when what comes before that panel is taller than the column */
5092
+ .rail > .panel:last-child {
5093
+ display: flex;
5094
+ flex-direction: column;
5095
+ flex: 0 1 auto;
5096
+ min-height: 0;
5097
+ }
5098
+
5099
+ .rail > .panel:last-child > :is(.panel-tb, .panel-shelf, .panel-foot) {
5100
+ flex: none;
5101
+ }
5102
+
5103
+ .rail > .panel:last-child > :not(.panel-tb, .panel-shelf, .panel-foot) {
5104
+ flex: 0 1 auto;
5105
+ min-height: 0;
5106
+ overflow-y: auto;
5107
+ }
5108
+
5109
+ /* a long name ends short of the bar's tools rather than wrapping the bar taller */
5110
+ .rail .panel-tb h2 {
5105
5111
  min-width: 0;
5112
+ overflow: hidden;
5113
+ overflow-wrap: normal;
5114
+ white-space: nowrap;
5115
+ text-overflow: ellipsis;
5116
+ }
5117
+
5118
+ /* the toggle is the button itself in the bar's lead */
5119
+ .rail-toggle {
5120
+ display: contents;
5106
5121
  }
5107
5122
 
5108
5123
  /* the splitter on the rail's right edge: a 12px strip from the edge outward, over the page's
@@ -5112,8 +5127,8 @@ dialog.veil:focus {
5112
5127
  .rail-resize {
5113
5128
  position: fixed;
5114
5129
  top: anchor(--topbar bottom, 0px);
5115
- bottom: var(--statusbar-h, 0px);
5116
- left: var(--rail);
5130
+ bottom: var(--statusbar-h);
5131
+ left: var(--railed-width, var(--rail));
5117
5132
  z-index: 1;
5118
5133
  width: 12px;
5119
5134
  cursor: col-resize;
@@ -5145,6 +5160,48 @@ dialog.veil:focus {
5145
5160
  display: none;
5146
5161
  }
5147
5162
 
5163
+ /* folded: the first panel stands its title bar on end on the ground where the rail stood, the
5164
+ toggle at its top and the title and count reading down; the rest of the rail and the
5165
+ splitter are gone, and the deck takes the width. Above 900px only: the drawer opens whole.
5166
+ Folding and unfolding move in three steps, as the drawer enters, but never while a pointer
5167
+ drags the splitter, where the rail follows the pointer */
5168
+ @media not (max-width: 900px) {
5169
+ .railed.folded {
5170
+ --railed-width: var(--rail-folded);
5171
+ }
5172
+
5173
+ .railed.folded > .rail > :not(.rail-head + .panel),
5174
+ .railed.folded > .rail > .rail-head + .panel > :not(.panel-tb),
5175
+ .railed.folded > .rail > .rail-head + .panel > .panel-tb > .panel-acts {
5176
+ display: none;
5177
+ }
5178
+
5179
+ .railed.folded > .rail > .rail-head + .panel {
5180
+ align-self: flex-start;
5181
+ }
5182
+
5183
+ .railed.folded > .rail > .rail-head + .panel > .panel-tb {
5184
+ writing-mode: vertical-rl;
5185
+ min-width: 31px;
5186
+ min-height: 0;
5187
+ padding: 3px 3px 12px;
5188
+ }
5189
+
5190
+ .railed.folded > .rail > .rail-head + .panel > .panel-tb > .meta {
5191
+ margin: 0;
5192
+ }
5193
+
5194
+ .railed,
5195
+ .railed > :is(.rail, .bench) {
5196
+ transition: var(--motion-card) steps(3, end);
5197
+ transition-property: padding-left, width, left;
5198
+ }
5199
+
5200
+ :root[data-pixel-paper-dragging] :is(.railed, .railed > .rail, .railed > .bench) {
5201
+ transition: none;
5202
+ }
5203
+ }
5204
+
5148
5205
  @media (max-width: 900px) {
5149
5206
  .railed {
5150
5207
  padding-left: 0;
@@ -5183,6 +5240,16 @@ dialog.veil:focus {
5183
5240
  display: inline-flex;
5184
5241
  justify-self: start;
5185
5242
  }
5243
+
5244
+ /* the drawer opens and closes but never folds, so it prints no toggle, and the bar the
5245
+ toggle led keeps its own padding */
5246
+ .panel-lead:has(> .rail-toggle) {
5247
+ display: none;
5248
+ }
5249
+
5250
+ .panel-tb:has(> .panel-lead > .rail-toggle) {
5251
+ padding-left: 12px;
5252
+ }
5186
5253
  }
5187
5254
 
5188
5255
  @keyframes railIn {
@@ -5196,21 +5263,24 @@ dialog.veil:focus {
5196
5263
  /* hung from the top bar's lower edge like the stage, down to the status bar, edge to edge, or
5197
5264
  from the rail's edge beside one (a fixed box takes nothing from .railed's padding). The head
5198
5265
  takes its own height while the work keeps at least --bench-work-min, or all but the head's
5199
- first 64px (its padding and a small button: the rail's open button) on a window too short
5266
+ first --bench-head-min (its padding and a small button: the rail's open button) on a window too short
5200
5267
  for both; past that the head scrolls itself. The work takes the rest and lays out what
5201
5268
  fills it (a reel's height is 100% of it). The page does not scroll */
5202
5269
  .bench {
5203
5270
  position: fixed;
5204
5271
  top: anchor(--topbar bottom, 0px);
5205
5272
  right: 0;
5206
- bottom: var(--statusbar-h, 0px);
5273
+ bottom: var(--statusbar-h);
5207
5274
  left: 0;
5208
5275
  display: grid;
5209
- grid-template-rows: minmax(0, max-content) minmax(min(var(--bench-work-min), 100% - 64px), 1fr);
5276
+ grid-template-rows: minmax(0, max-content) minmax(
5277
+ min(var(--bench-work-min), 100% - var(--bench-head-min)),
5278
+ 1fr
5279
+ );
5210
5280
  }
5211
5281
 
5212
5282
  .railed > .bench {
5213
- left: var(--rail);
5283
+ left: var(--railed-width, var(--rail));
5214
5284
  }
5215
5285
 
5216
5286
  /* the head lines up with a reel's windows, a reel's gutter in from the edge; the reel's own
@@ -5248,7 +5318,7 @@ dialog.veil:focus {
5248
5318
  position: fixed;
5249
5319
  top: anchor(--topbar bottom, 0px);
5250
5320
  right: 0;
5251
- bottom: var(--statusbar-h, 0px);
5321
+ bottom: var(--statusbar-h);
5252
5322
  left: 0;
5253
5323
  overflow: hidden;
5254
5324
  }
@@ -5347,8 +5417,7 @@ dialog.veil:focus {
5347
5417
  border-color: var(--paper);
5348
5418
  }
5349
5419
 
5350
- .window > .panel-tb .iconbtn,
5351
- .window > .panel-tb .iconbtn.quiet {
5420
+ .window > .panel-tb .iconbtn {
5352
5421
  color: inherit;
5353
5422
  }
5354
5423
 
@@ -5558,7 +5627,7 @@ dialog.veil:focus {
5558
5627
  }
5559
5628
 
5560
5629
  .reel-pane.drag-dim {
5561
- opacity: 0.4;
5630
+ opacity: var(--fade-dragged);
5562
5631
  }
5563
5632
 
5564
5633
  /* only the grips lift: a pane's text selects and its terminal takes the pointer */
@@ -5767,7 +5836,6 @@ dialog.veil:focus {
5767
5836
  inset: 0;
5768
5837
  width: 100%;
5769
5838
  height: 100%;
5770
- margin: 0;
5771
5839
  opacity: 0;
5772
5840
  appearance: none;
5773
5841
  cursor: pointer;
@@ -5826,7 +5894,7 @@ dialog.veil:focus {
5826
5894
  padding from the corner), so the stylesheet raises it clear of a banner, its anchor when one
5827
5895
  is showing, or of a status bar, and sets the gap. A phone spans it across the bottom */
5828
5896
  .toasts .toast-stack {
5829
- bottom: calc(anchor(--banner top, calc(var(--statusbar-h, 0px) + 4px)) - 4px) !important;
5897
+ bottom: calc(anchor(--banner top, calc(var(--statusbar-h) + 4px)) - 4px) !important;
5830
5898
  gap: 10px !important;
5831
5899
  width: min(392px, 100vw);
5832
5900
  }
@@ -5874,21 +5942,19 @@ dialog.veil:focus {
5874
5942
  }
5875
5943
  }
5876
5944
 
5877
- @media (prefers-reduced-motion: reduce) {
5878
- .toasts .toast {
5879
- animation: none;
5880
- }
5881
- }
5882
-
5883
5945
  /* ---------- reduced motion ---------- */
5884
5946
 
5885
5947
  @media (prefers-reduced-motion: reduce) {
5886
- .cursor {
5887
- animation: none;
5888
- }
5948
+ .cursor,
5889
5949
  .veil-backdrop,
5890
5950
  .card,
5891
- .rail[popover]:popover-open {
5951
+ .rail[popover]:popover-open,
5952
+ .toasts .toast {
5892
5953
  animation: none;
5893
5954
  }
5955
+
5956
+ .railed,
5957
+ .railed > :is(.rail, .bench) {
5958
+ transition: none;
5959
+ }
5894
5960
  }