@crewlethq/ui 0.39.0 → 0.40.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 (93) hide show
  1. package/README.md +43 -1
  2. package/dist/AppShell/AppShell.d.ts +13 -2
  3. package/dist/AppShell/index.js +1 -1
  4. package/dist/{AppShell-NDU4XMGF.css → AppShell-NPSWZ3XW.css} +45 -4
  5. package/dist/ArtifactBar/index.js +6 -5
  6. package/dist/AvatarPicker/index.js +10 -6
  7. package/dist/CatalogTile/index.js +1 -1
  8. package/dist/{CatalogTile-TGR2ZZVQ.css → CatalogTile-XL4XLFUH.css} +8 -4
  9. package/dist/CharacterPicker/index.js +2 -2
  10. package/dist/Charts/Histogram.d.ts +71 -0
  11. package/dist/Charts/index.d.ts +2 -0
  12. package/dist/Charts/index.js +1 -1
  13. package/dist/{Charts-MBJG72BS.css → Charts-TZ744HT6.css} +118 -0
  14. package/dist/DataGrid/DataGrid.d.ts +267 -0
  15. package/dist/DataGrid/index.d.ts +3 -0
  16. package/dist/DataGrid/index.js +7 -0
  17. package/dist/DataGrid-AQKPJD7W.css +482 -0
  18. package/dist/HuePicker/index.js +11 -4
  19. package/dist/LayersList/index.js +2 -2
  20. package/dist/LockedLabel/LockedLabel.d.ts +34 -0
  21. package/dist/LockedLabel/index.d.ts +3 -0
  22. package/dist/LockedLabel/index.js +3 -0
  23. package/dist/LockedLabel-VQEGEB7G.css +16 -0
  24. package/dist/MarkdownEditor/index.js +8 -5
  25. package/dist/MergeConflicts/index.js +11 -5
  26. package/dist/PageNote/PageNote.d.ts +14 -0
  27. package/dist/PageNote/index.d.ts +3 -0
  28. package/dist/PageNote/index.js +2 -0
  29. package/dist/PageNote-RHLXH3ML.css +12 -0
  30. package/dist/PropertyList/PropertyList.d.ts +88 -0
  31. package/dist/PropertyList/index.d.ts +3 -0
  32. package/dist/PropertyList/index.js +7 -0
  33. package/dist/PropertyList-SCYM66LL.css +96 -0
  34. package/dist/RelatedRow/RelatedRow.d.ts +27 -0
  35. package/dist/RelatedRow/index.d.ts +3 -0
  36. package/dist/RelatedRow/index.js +9 -0
  37. package/dist/RelatedRow-2FVS6QQA.css +6 -0
  38. package/dist/RichEditor/index.js +1 -1
  39. package/dist/SectionFrame/SectionFrame.d.ts +76 -0
  40. package/dist/SectionFrame/index.d.ts +3 -0
  41. package/dist/SectionFrame/index.js +7 -0
  42. package/dist/SectionFrame-M62UUVFQ.css +164 -0
  43. package/dist/SegmentedControl/index.js +11 -4
  44. package/dist/SheetColumnEditor/index.js +6 -5
  45. package/dist/SheetGrid/index.js +3 -3
  46. package/dist/SidebarNav/SidebarNav.d.ts +35 -2
  47. package/dist/SidebarNav/index.js +2 -1
  48. package/dist/{SidebarNav-7SGUZYKK.css → SidebarNav-YI74SPDC.css} +10 -0
  49. package/dist/Tabs/Tabs.d.ts +55 -1
  50. package/dist/Tabs/fold.d.ts +54 -0
  51. package/dist/Tabs/index.d.ts +1 -1
  52. package/dist/Tabs/index.js +9 -2
  53. package/dist/Tabs/roving.d.ts +3 -3
  54. package/dist/{Tabs-WIF7457H.css → Tabs-S7F4RWAN.css} +77 -0
  55. package/dist/TagsInput/index.js +1 -1
  56. package/dist/ThemeGallery/index.js +2 -2
  57. package/dist/ThemeSwitcher/index.js +12 -5
  58. package/dist/VersionCompare/index.js +12 -5
  59. package/dist/{chunk-B5J23C73.js → chunk-2PEXZ7L4.js} +1 -1
  60. package/dist/{chunk-TZYFTC4M.js → chunk-2VOHUGUA.js} +1 -1
  61. package/dist/{chunk-2QZ2VPHR.js → chunk-4OK4DX3V.js} +2 -2
  62. package/dist/{chunk-ECGGQX2H.js → chunk-A44YHLCQ.js} +2 -2
  63. package/dist/{chunk-F4LPQA4E.js → chunk-BA32AVKS.js} +1 -1
  64. package/dist/chunk-CV4NES3P.js +9 -0
  65. package/dist/{chunk-PPHTIKZO.js → chunk-E4BOVKNJ.js} +1 -1
  66. package/dist/{chunk-W7PAIVAP.js → chunk-E7QLG3PG.js} +30 -9
  67. package/dist/{chunk-RKKO7QHH.js → chunk-EGMQURBR.js} +5 -4
  68. package/dist/{chunk-GMW4ZHST.js → chunk-EX22Q5SH.js} +2 -2
  69. package/dist/{chunk-F3WZ5AKM.js → chunk-GFYQKMQZ.js} +1 -1
  70. package/dist/{chunk-HG5VF3TZ.js → chunk-HMVQQEHW.js} +91 -2
  71. package/dist/chunk-INVSUFJK.js +71 -0
  72. package/dist/{chunk-4LRAJXHL.js → chunk-JSWOXRRE.js} +1 -1
  73. package/dist/{chunk-DYB66CNM.js → chunk-KKNHMXTE.js} +6 -3
  74. package/dist/{chunk-ZMDYQ2HH.js → chunk-KWWP3D7M.js} +1 -1
  75. package/dist/{chunk-46RL3E54.js → chunk-M6NQ4XGK.js} +1 -1
  76. package/dist/chunk-OHGH7O6T.js +19 -0
  77. package/dist/{chunk-4ISUIS6F.js → chunk-OOC7Q67K.js} +1 -1
  78. package/dist/{chunk-XNXK5MA4.js → chunk-PCT47E7O.js} +1 -1
  79. package/dist/{chunk-X3UYTAOG.js → chunk-PFZOFAQ6.js} +1 -1
  80. package/dist/{chunk-YEVG2X5R.js → chunk-SNQRGH4A.js} +1 -1
  81. package/dist/chunk-T6MXORP5.js +116 -0
  82. package/dist/chunk-X4IXXLWM.js +306 -0
  83. package/dist/chunk-XIDD7PJO.js +416 -0
  84. package/dist/chunk-ZUTUI27P.js +21 -0
  85. package/dist/generated/index.d.ts +6 -0
  86. package/dist/generated/index.js +60 -54
  87. package/dist/index.js +60 -54
  88. package/dist/styles.css +1061 -17
  89. package/package.json +3 -3
  90. package/dist/chunk-7SDUKCNW.js +0 -141
  91. package/dist/{Editor-QV4JP242.js → Editor-IRDQ3JDZ.js} +1 -1
  92. package/dist/{chunk-JZPK4IXR.js → chunk-3PR65I3H.js} +2 -2
  93. /package/dist/{chunk-QRLIWCLX.js → chunk-S3QTFUJX.js} +0 -0
package/dist/styles.css CHANGED
@@ -702,7 +702,7 @@
702
702
  }
703
703
 
704
704
 
705
- /* AppShell-NDU4XMGF.css */
705
+ /* AppShell-NPSWZ3XW.css */
706
706
  /*
707
707
  * The application frame: a rail on the FRAME, and the screen on a SHEET that
708
708
  * floats beside it.
@@ -835,6 +835,8 @@
835
835
  .crewlet-app-shell__rail-head {
836
836
  display: flex;
837
837
  align-items: center;
838
+ gap: var(--spacing-2);
839
+ min-width: 0;
838
840
  flex: none;
839
841
  box-sizing: border-box;
840
842
  min-height: calc(var(--size-shell-inset) + var(--crewlet-app-shell-topbar));
@@ -848,6 +850,31 @@
848
850
  scrollbar-color: var(--color-scrollbar) transparent;
849
851
  }
850
852
 
853
+ /*
854
+ * THE HEAD'S FIRST CHILD TAKES ITS WIDTH: a lockup alone on its line, whose
855
+ * name truncates at the rail's edge rather than wrapping or pushing the head
856
+ * wider. It was every application's own wrapper and rule.
857
+ */
858
+ .crewlet-app-shell__rail-head > :first-child {
859
+ flex: 1 1 auto;
860
+ min-width: 0;
861
+ }
862
+
863
+ /*
864
+ * THE RAIL'S FIELD ON THE NAV'S COLUMNS. It stands on the nav's gutter, so
865
+ * its right edge is where every row's background ends; and its glyph stands
866
+ * on the nav's glyph column: a row's glyph is the gutter and the row's pad
867
+ * in, the field's is the gutter, its own 1px edge and its pad
868
+ * (`SearchTrigger`'s two steps and a half), so the inset at its start makes
869
+ * up the difference from those measures.
870
+ */
871
+ .crewlet-app-shell__rail-search {
872
+ padding: 0 var(--size-nav-gutter) var(--spacing-3);
873
+ padding-inline-start: calc(
874
+ var(--size-nav-gutter) + var(--size-nav-row-pad) - (var(--spacing-2) + var(--spacing-1) / 2) - 1px
875
+ );
876
+ }
877
+
851
878
  /* The same gutter the nav takes, so what the foot says lines up with the rows
852
879
  above it rather than sitting further out. */
853
880
  .crewlet-app-shell__rail-foot {
@@ -1193,6 +1220,15 @@
1193
1220
  overflow-y: auto;
1194
1221
  overflow-x: hidden;
1195
1222
  scrollbar-gutter: stable;
1223
+ /*
1224
+ * A SIZE CONTAINER, so a box inside the screen can be as tall as the view
1225
+ * it scrolls in (`100cqb`): a column that sticks beside the screen
1226
+ * (`SectionFrame`), a record bounded by the window. The scroller's size is
1227
+ * the shell's, never its content's, so containing it costs nothing. A box
1228
+ * inside an inline-size container (a card, a stat row) reaches past it to
1229
+ * this one for the block axis.
1230
+ */
1231
+ container-type: size;
1196
1232
  }
1197
1233
 
1198
1234
  /* No focus rule of its own: `main` takes focus only from the skip link, and a
@@ -1210,12 +1246,17 @@
1210
1246
  }
1211
1247
 
1212
1248
  /* A screen that draws to the bottom of the window: the scroller stops
1213
- scrolling and the content column takes the height that is left. It
1214
- reserves no scrollbar gutter either, since nothing in it scrolls: the
1215
- reserved strip was a dead band down the screen's end edge. */
1249
+ scrolling and the content column takes the height that is left.
1250
+
1251
+ IT KEEPS THE GUTTER RESERVED, like every other screen. The top bar's end
1252
+ inset counts the scroller's gutter (`--crewlet-app-shell-gutter`, measured
1253
+ by the shell), so a fill screen that reserved none put the bar's controls
1254
+ one gutter further out than on the screen beside it: with classic
1255
+ scrollbars, Add seat moved 11px between an org chart and its roster, two
1256
+ tabs of one page. A strip at the end edge of a full-screen canvas is the
1257
+ smaller cost than a bar that moves under the pointer. */
1216
1258
  .crewlet-app-shell--fill .crewlet-app-shell__main {
1217
1259
  overflow: hidden;
1218
- scrollbar-gutter: auto;
1219
1260
  }
1220
1261
 
1221
1262
  .crewlet-app-shell--fill .crewlet-app-shell__content {
@@ -6810,7 +6851,7 @@ a.crewlet-breadcrumb__crumb:focus-visible {
6810
6851
  }
6811
6852
 
6812
6853
 
6813
- /* CatalogTile-TGR2ZZVQ.css */
6854
+ /* CatalogTile-XL4XLFUH.css */
6814
6855
  /*
6815
6856
  * CatalogTile: mark, name and state, one sentence, and a foot with a quiet
6816
6857
  * fact and one action.
@@ -6841,7 +6882,7 @@ a.crewlet-breadcrumb__crumb:focus-visible {
6841
6882
 
6842
6883
  .crewlet-catalog-tile__head {
6843
6884
  display: flex;
6844
- align-items: center;
6885
+ align-items: flex-start;
6845
6886
  gap: var(--spacing-3);
6846
6887
  min-width: 0;
6847
6888
  }
@@ -6859,13 +6900,17 @@ a.crewlet-breadcrumb__crumb:focus-visible {
6859
6900
  color: var(--color-text-primary);
6860
6901
  }
6861
6902
 
6862
- /* The name, and under it the state when there is one; centred on the mark
6863
- either way, so a tile with no state is not a tile with a hole in it. */
6903
+ /* The name, and under it the state when there is one. THE NAME STANDS ON ONE
6904
+ LINE ACROSS A ROW whether or not a tile has a state: centred on the mark, a
6905
+ name with a pill under it rose 13px above its stateless neighbour's, so the
6906
+ names of one row stood at two heights. It starts one step below the mark's
6907
+ top edge in every tile instead. */
6864
6908
  .crewlet-catalog-tile__title {
6865
6909
  display: flex;
6866
6910
  flex-direction: column;
6867
6911
  align-items: flex-start;
6868
- justify-content: center;
6912
+ justify-content: flex-start;
6913
+ padding-top: var(--spacing-1);
6869
6914
  gap: var(--spacing-1);
6870
6915
  min-width: 0;
6871
6916
  }
@@ -7014,7 +7059,7 @@ a.crewlet-breadcrumb__crumb:focus-visible {
7014
7059
  }
7015
7060
 
7016
7061
 
7017
- /* Charts-MBJG72BS.css */
7062
+ /* Charts-TZ744HT6.css */
7018
7063
  /* The chart kit: a legend, a ranked bar list, a stacked bar, stacked
7019
7064
  columns, an activity strip, a time series and the reading layer they share. Hand-drawn rather than a charting library, for one reason that
7020
7065
  decides it: every mark here reads tokens, in two themes, at the contrast
@@ -7996,6 +8041,124 @@ a.crewlet-breadcrumb__crumb:focus-visible {
7996
8041
  pointer-events: none;
7997
8042
  }
7998
8043
 
8044
+ /* ─── Histogram, a log's own time axis ─────────────────────────── */
8045
+
8046
+ /*
8047
+ * Time runs left to right on this axis in every writing direction, as it does
8048
+ * on every chart, and the ticks are placed on physical sides to match.
8049
+ */
8050
+ .crewlet-histogram {
8051
+ display: flex;
8052
+ flex-direction: column;
8053
+ min-width: 0;
8054
+ direction: ltr;
8055
+ }
8056
+
8057
+ /* The plot's bottom border is the axis line the ticks hang under. */
8058
+ .crewlet-histogram__plot {
8059
+ display: flex;
8060
+ align-items: flex-end;
8061
+ gap: 1px;
8062
+ width: 100%;
8063
+ height: var(--crewlet-histogram-height, 96px);
8064
+ padding: var(--spacing-1) 0;
8065
+ border-bottom: 1px solid var(--color-border-hover);
8066
+ }
8067
+
8068
+ /* The slot is the control, and the whole of it is the target. */
8069
+ .crewlet-histogram__bar {
8070
+ all: unset;
8071
+ flex: 1 1 0;
8072
+ min-width: 2px;
8073
+ height: 100%;
8074
+ display: flex;
8075
+ align-items: flex-end;
8076
+ justify-content: center;
8077
+ }
8078
+
8079
+ button.crewlet-histogram__bar {
8080
+ cursor: pointer;
8081
+ }
8082
+
8083
+ /* A slot draws no edge, so its ring stands off it. `all: unset` takes the
8084
+ baseline ring away; this states it again at a weight the reset cannot
8085
+ out-rank. */
8086
+ .crewlet-histogram__bar:focus-visible {
8087
+ outline: 2px solid var(--color-focus);
8088
+ outline-offset: 2px;
8089
+ }
8090
+
8091
+ /*
8092
+ * A count is data, so it is drawn in the data ramp; the accent is kept for the
8093
+ * bar the reader is pointing at, the selection a click is about to make. The
8094
+ * fill stacks from its foot, so the failed share sits at its bottom. Floors in
8095
+ * pixels: an empty bucket at two, the smallest real count at three.
8096
+ */
8097
+ .crewlet-histogram__fill {
8098
+ display: flex;
8099
+ flex-direction: column;
8100
+ justify-content: flex-end;
8101
+ overflow: hidden;
8102
+ width: 63%;
8103
+ min-width: 2px;
8104
+ max-width: var(--spacing-7);
8105
+ height: var(--crewlet-histogram-fill, 0%);
8106
+ min-height: 3px;
8107
+ background: var(--color-data-1);
8108
+ border-radius: var(--radius-sm) var(--radius-sm) 0 0;
8109
+ transition: background var(--motion-duration-fast) var(--motion-easing-default);
8110
+ }
8111
+
8112
+ .crewlet-histogram__part {
8113
+ display: block;
8114
+ width: 100%;
8115
+ height: var(--crewlet-histogram-part, 0%);
8116
+ background: var(--color-feedback-danger);
8117
+ }
8118
+
8119
+ button.crewlet-histogram__bar:hover > .crewlet-histogram__fill,
8120
+ button.crewlet-histogram__bar:focus-visible > .crewlet-histogram__fill {
8121
+ background: var(--color-brand-accent);
8122
+ }
8123
+
8124
+ /* An empty bucket is a visible floor in the tone an axis is ruled in:
8125
+ present, and plainly not a quantity. */
8126
+ .crewlet-histogram__bar[data-empty] > .crewlet-histogram__fill {
8127
+ min-height: 2px;
8128
+ background: var(--color-border-strong);
8129
+ }
8130
+
8131
+ button.crewlet-histogram__bar[data-empty]:hover > .crewlet-histogram__fill,
8132
+ button.crewlet-histogram__bar[data-empty]:focus-visible > .crewlet-histogram__fill {
8133
+ background: var(--color-border-strong-hover);
8134
+ }
8135
+
8136
+ /*
8137
+ * The dates under the bars. Absolutely placed, so a tick sits over the bucket
8138
+ * it names; the row states its own height because absolutely placed children
8139
+ * contribute none.
8140
+ */
8141
+ .crewlet-histogram__axis {
8142
+ position: relative;
8143
+ height: calc(var(--font-size-2xs) * var(--font-line-height-normal));
8144
+ margin-top: 2px;
8145
+ }
8146
+
8147
+ .crewlet-histogram__tick {
8148
+ position: absolute;
8149
+ top: 0;
8150
+ font-size: var(--font-size-2xs);
8151
+ color: var(--color-text-tertiary);
8152
+ font-variant-numeric: tabular-nums;
8153
+ white-space: nowrap;
8154
+ }
8155
+
8156
+ @media (prefers-reduced-motion: reduce) {
8157
+ .crewlet-histogram__fill {
8158
+ transition: none;
8159
+ }
8160
+ }
8161
+
7999
8162
 
8000
8163
  /* Checkbox-ALWG3WV2.css */
8001
8164
  /*
@@ -9786,10 +9949,495 @@ a.crewlet-breadcrumb__crumb:focus-visible {
9786
9949
  opacity: 0.5;
9787
9950
  }
9788
9951
 
9789
- .crewlet-dashboard-cover--empty {
9790
- display: flex;
9791
- align-items: center;
9792
- justify-content: center;
9952
+ .crewlet-dashboard-cover--empty {
9953
+ display: flex;
9954
+ align-items: center;
9955
+ justify-content: center;
9956
+ }
9957
+
9958
+
9959
+ /* DataGrid-AQKPJD7W.css */
9960
+ /*
9961
+ * DataGrid: a list as columns, one track list on the grid.
9962
+ *
9963
+ * THE GRID MAKES NO SCROLLPORT OF ITS OWN. `overflow: clip` rounds the rows off
9964
+ * at the corner exactly as `hidden` would, and it is the difference between a
9965
+ * sticky head that works and one that cannot: `hidden` makes a scroll
9966
+ * container, a sticky box is confined to its nearest scrollport, and this one
9967
+ * grows to its rows, so its offset is always 0. The head sticks against the
9968
+ * page's own scroller; an application whose scroller carries a sticky bar of
9969
+ * its own sets `--crewlet-data-grid-sticky-top` to that bar's height.
9970
+ *
9971
+ * THE COLUMNS BELONG TO THE GRID, NOT TO A ROW. The tracks are declared once,
9972
+ * on the grid (its inline `grid-template-columns`), and the head, the body,
9973
+ * the bands and the rows are `subgrid` passthroughs, so a head cell and a cell
9974
+ * twenty rows down size the same track. Everything that is not a row of cells
9975
+ * spans the whole width.
9976
+ */
9977
+
9978
+ .crewlet-data-grid {
9979
+ display: grid;
9980
+ min-width: 0;
9981
+ border: 1px solid var(--color-border-hover);
9982
+ border-radius: var(--radius-md);
9983
+ overflow: clip;
9984
+ background: var(--color-surface-subtle);
9985
+ }
9986
+
9987
+ /*
9988
+ * A CARD'S BODY (`flush`, and every grid straight in a Card or its body, told
9989
+ * or not): the card is the frame, so the grid draws none of its own and one
9990
+ * rule parts it from the card's head. Under the card's header, the header's
9991
+ * own rule is that one.
9992
+ */
9993
+ .crewlet-data-grid[data-flush],
9994
+ .crewlet-card > .crewlet-data-grid,
9995
+ .crewlet-card__body > .crewlet-data-grid {
9996
+ border: 0;
9997
+ border-top: 1px solid var(--color-border-default);
9998
+ border-radius: var(--radius-none);
9999
+ background: transparent;
10000
+ }
10001
+
10002
+ .crewlet-card__header + .crewlet-data-grid {
10003
+ border-top: 0;
10004
+ }
10005
+
10006
+ /* A full-width band by default: the head, the body, the foot, the reset and
10007
+ the empty state, which is the one child when the grid carries no tracks. */
10008
+ .crewlet-data-grid > * {
10009
+ grid-column: 1 / -1;
10010
+ }
10011
+
10012
+ .crewlet-data-grid__head,
10013
+ .crewlet-data-grid__body,
10014
+ .crewlet-data-grid__band,
10015
+ .crewlet-data-grid__row {
10016
+ display: grid;
10017
+ grid-template-columns: subgrid;
10018
+ grid-column: 1 / -1;
10019
+ }
10020
+
10021
+ .crewlet-data-grid__band-head,
10022
+ .crewlet-data-grid__band-foot {
10023
+ grid-column: 1 / -1;
10024
+ }
10025
+
10026
+ /*
10027
+ * The head: a floor at the row height (density shrinks the padding, not the
10028
+ * label), on the raised ground, sticky at the application's offset.
10029
+ */
10030
+ .crewlet-data-grid__head {
10031
+ align-items: center;
10032
+ min-height: var(--size-row-md);
10033
+ border-bottom: 1px solid var(--color-border-hover);
10034
+ background: var(--color-surface-elevated);
10035
+ position: sticky;
10036
+ top: var(--crewlet-data-grid-sticky-top, var(--spacing-0));
10037
+ z-index: var(--z-index-sticky);
10038
+ }
10039
+
10040
+ /*
10041
+ * THE LIST TABLE'S HEAD: the micro-label register every table takes, 11/500
10042
+ * uppercase. A sortable head is a button with its chrome reset; the reset
10043
+ * takes the focus ring with it, so the ring is restated below.
10044
+ */
10045
+ .crewlet-data-grid__th {
10046
+ display: flex;
10047
+ align-items: center;
10048
+ gap: var(--spacing-1);
10049
+ padding: var(--spacing-2) var(--spacing-3);
10050
+ font-size: var(--font-size-2xs);
10051
+ font-weight: var(--font-weight-medium);
10052
+ text-transform: uppercase;
10053
+ letter-spacing: var(--font-letter-spacing-wide);
10054
+ color: var(--color-text-tertiary);
10055
+ cursor: pointer;
10056
+ min-width: 0;
10057
+ transition: color var(--motion-duration-fast) var(--motion-easing-default);
10058
+ }
10059
+
10060
+ .crewlet-data-grid__th--plain {
10061
+ cursor: default;
10062
+ }
10063
+
10064
+ /* A sortable head's control fills the head: the whole cell is the target. */
10065
+ .crewlet-data-grid__sort {
10066
+ all: unset;
10067
+ display: flex;
10068
+ align-items: center;
10069
+ gap: var(--spacing-1);
10070
+ flex: 1 1 auto;
10071
+ min-width: 0;
10072
+ margin: calc(-1 * var(--spacing-2)) calc(-1 * var(--spacing-3));
10073
+ padding: var(--spacing-2) var(--spacing-3);
10074
+ cursor: pointer;
10075
+ }
10076
+
10077
+ .crewlet-data-grid__th--right .crewlet-data-grid__sort {
10078
+ justify-content: flex-end;
10079
+ }
10080
+
10081
+ .crewlet-data-grid__th:not(.crewlet-data-grid__th--plain):hover,
10082
+ .crewlet-data-grid__th--sorted {
10083
+ color: var(--color-text-primary);
10084
+ }
10085
+
10086
+ .crewlet-data-grid__th--right {
10087
+ justify-content: flex-end;
10088
+ }
10089
+
10090
+ .crewlet-data-grid__sort:focus-visible,
10091
+ .crewlet-data-grid__cols-reset:focus-visible {
10092
+ outline: 2px solid var(--color-focus);
10093
+ outline-offset: var(--size-focus-ring-inset-offset);
10094
+ }
10095
+
10096
+ .crewlet-data-grid__body {
10097
+ min-width: 0;
10098
+ }
10099
+
10100
+ .crewlet-data-grid__row {
10101
+ align-items: center;
10102
+ min-height: var(--size-row-md);
10103
+ border-bottom: 1px solid var(--color-border-default);
10104
+ color: inherit;
10105
+ cursor: pointer;
10106
+ /* The containing block for the row's link. */
10107
+ position: relative;
10108
+ transition: background var(--motion-duration-fast) var(--motion-easing-default);
10109
+ }
10110
+
10111
+ /* THE ROW'S OWN LINK, STRETCHED OVER IT, out of flow so it takes no track. */
10112
+ .crewlet-data-grid__row-link {
10113
+ position: absolute;
10114
+ inset: 0;
10115
+ }
10116
+
10117
+ /* A button overlay (a row that acts and has no address) gives up the chrome a
10118
+ button brings, and draws the focus ring inside the row. */
10119
+ button.crewlet-data-grid__row-link {
10120
+ all: unset;
10121
+ position: absolute;
10122
+ inset: 0;
10123
+ cursor: pointer;
10124
+ }
10125
+
10126
+ .crewlet-data-grid__row-link:focus-visible {
10127
+ outline: 2px solid var(--color-focus);
10128
+ outline-offset: var(--size-focus-ring-inset-offset);
10129
+ }
10130
+
10131
+ /*
10132
+ * AND THE CELLS' OWN CONTROLS SIT ABOVE IT: positioned and later in the
10133
+ * document than the overlay, they win the hit test in the same stacking
10134
+ * context, with no z-index to reason about against the sticky head. A cell's
10135
+ * element that is not a link or a button but must take its own clicks (a
10136
+ * refusal sentence a reader selects) carries `data-above-row`.
10137
+ */
10138
+ .crewlet-data-grid__row a:not(.crewlet-data-grid__row-link),
10139
+ .crewlet-data-grid__row button:not(.crewlet-data-grid__row-link),
10140
+ .crewlet-data-grid__row [data-above-row] {
10141
+ position: relative;
10142
+ }
10143
+
10144
+ .crewlet-data-grid__row:last-child {
10145
+ border-bottom: none;
10146
+ }
10147
+
10148
+ .crewlet-data-grid__row:hover {
10149
+ background: var(--color-surface-hover);
10150
+ }
10151
+
10152
+ .crewlet-data-grid__row--selected,
10153
+ .crewlet-data-grid__row--selected:hover {
10154
+ background: var(--color-brand-accent-soft);
10155
+ }
10156
+
10157
+ .crewlet-data-grid__row--cursor {
10158
+ box-shadow: inset 2px 0 0 var(--color-brand-accent);
10159
+ }
10160
+
10161
+ /* A FAILED ROW IS MARKED ON ITS EDGE, not tinted: the status column already
10162
+ says so, and two signals for one fact teach a reader to trust neither. */
10163
+ .crewlet-data-grid__row--failed {
10164
+ box-shadow: inset 2px 0 0 var(--color-feedback-danger-ink);
10165
+ }
10166
+
10167
+ .crewlet-data-grid__cell {
10168
+ padding: var(--spacing-1) var(--spacing-3);
10169
+ font-size: var(--font-size-compact);
10170
+ min-width: 0;
10171
+ display: flex;
10172
+ align-items: center;
10173
+ gap: var(--spacing-2);
10174
+ }
10175
+
10176
+ /*
10177
+ * A SHRINK COLUMN does not wrap inside its capped track, and does not paint
10178
+ * outside it: a nowrap cell narrower than its content would spill over the
10179
+ * column beside it. `clip`, since a scrollport here would cut the sticky head.
10180
+ */
10181
+ .crewlet-data-grid__th--shrink,
10182
+ .crewlet-data-grid__cell--shrink {
10183
+ white-space: nowrap;
10184
+ overflow: clip;
10185
+ }
10186
+
10187
+ .crewlet-data-grid__cell--right {
10188
+ justify-content: flex-end;
10189
+ }
10190
+
10191
+ .crewlet-data-grid__truncate {
10192
+ min-width: 0;
10193
+ overflow: hidden;
10194
+ text-overflow: ellipsis;
10195
+ white-space: nowrap;
10196
+ }
10197
+
10198
+ .crewlet-data-grid__band + .crewlet-data-grid__band {
10199
+ border-top: 1px solid var(--color-border-hover);
10200
+ }
10201
+
10202
+ .crewlet-data-grid__band-head,
10203
+ .crewlet-data-grid__band-foot {
10204
+ display: flex;
10205
+ }
10206
+
10207
+ /* The band row's one cell lays its parts out on the row's own flex line. */
10208
+ .crewlet-data-grid__band-cell {
10209
+ display: contents;
10210
+ }
10211
+
10212
+ .crewlet-data-grid__band-head {
10213
+ display: flex;
10214
+ align-items: center;
10215
+ gap: var(--spacing-2);
10216
+ padding: var(--spacing-2) var(--spacing-3);
10217
+ background: var(--color-surface-elevated);
10218
+ font-size: var(--font-size-xs);
10219
+ font-weight: var(--font-weight-semibold);
10220
+ position: sticky;
10221
+ /* Under the column heads, which are a row tall and parked at the offset;
10222
+ confined to its own band, so it leaves with the band. Above the rows
10223
+ (positioned for the row link) and below the heads. */
10224
+ top: calc(var(--crewlet-data-grid-sticky-top, var(--spacing-0)) + var(--size-row-md));
10225
+ z-index: var(--z-index-raised);
10226
+ }
10227
+
10228
+ /* A SECOND AXIS IS A BAND INSIDE A BAND, inset and quieter, so it does not
10229
+ read as its parent's sibling; and it draws no rule above itself. */
10230
+ .crewlet-data-grid__band .crewlet-data-grid__band > .crewlet-data-grid__band-head {
10231
+ padding-left: calc(var(--spacing-3) + var(--spacing-4));
10232
+ background: var(--color-surface-subtle);
10233
+ font-weight: var(--font-weight-medium);
10234
+ color: var(--color-text-tertiary);
10235
+ }
10236
+
10237
+ .crewlet-data-grid__band .crewlet-data-grid__band + .crewlet-data-grid__band {
10238
+ border-top: none;
10239
+ }
10240
+
10241
+ .crewlet-data-grid__band-count {
10242
+ margin-left: auto;
10243
+ color: var(--color-text-tertiary);
10244
+ font-weight: var(--font-weight-regular);
10245
+ font-variant-numeric: tabular-nums;
10246
+ }
10247
+
10248
+ .crewlet-data-grid__band-foot {
10249
+ padding: var(--spacing-1) var(--spacing-3);
10250
+ font-size: var(--font-size-2xs);
10251
+ color: var(--color-text-tertiary);
10252
+ background: var(--color-surface-elevated);
10253
+ }
10254
+
10255
+ .crewlet-data-grid__band-foot a {
10256
+ color: var(--color-brand-accent-ink);
10257
+ }
10258
+
10259
+ .crewlet-data-grid__band-foot a:hover {
10260
+ color: var(--color-text-primary);
10261
+ }
10262
+
10263
+ .crewlet-data-grid__foot {
10264
+ display: flex;
10265
+ align-items: center;
10266
+ gap: var(--spacing-2);
10267
+ padding: var(--spacing-2) var(--spacing-3);
10268
+ border-top: 1px solid var(--color-border-hover);
10269
+ background: var(--color-surface-elevated);
10270
+ font-size: var(--font-size-xs);
10271
+ }
10272
+
10273
+ .crewlet-data-grid__foot-spacer {
10274
+ flex: 1 1 auto;
10275
+ }
10276
+
10277
+ .crewlet-data-grid__note {
10278
+ font-size: var(--font-size-xs);
10279
+ color: var(--color-text-tertiary);
10280
+ }
10281
+
10282
+ .crewlet-data-grid__cols-reset {
10283
+ all: unset;
10284
+ /* After the reset, which takes `grid-column` too. */
10285
+ grid-column: 1 / -1;
10286
+ padding: var(--spacing-1) var(--spacing-3);
10287
+ font-size: var(--font-size-2xs);
10288
+ color: var(--color-brand-accent-ink);
10289
+ cursor: pointer;
10290
+ text-align: left;
10291
+ }
10292
+
10293
+ /* ---- The column chooser ------------------------------------------------ */
10294
+
10295
+ .crewlet-column-chooser__label {
10296
+ font-size: var(--font-size-2xs);
10297
+ font-weight: var(--font-weight-medium);
10298
+ letter-spacing: var(--font-letter-spacing-wide);
10299
+ text-transform: uppercase;
10300
+ color: var(--color-text-tertiary);
10301
+ }
10302
+
10303
+ /* TWO COLUMNS: a single file of short words makes a menu as tall as the grid
10304
+ has columns. */
10305
+ .crewlet-column-chooser__choices {
10306
+ display: grid;
10307
+ grid-template-columns: repeat(2, minmax(0, 1fr));
10308
+ gap: var(--spacing-1) var(--spacing-3);
10309
+ }
10310
+
10311
+ /* The pointer target is the row, not the 13px box. */
10312
+ .crewlet-column-chooser__choice {
10313
+ display: flex;
10314
+ align-items: center;
10315
+ gap: var(--spacing-2);
10316
+ min-height: var(--size-target-min);
10317
+ font-size: var(--font-size-compact);
10318
+ color: var(--color-text-secondary);
10319
+ cursor: pointer;
10320
+ }
10321
+
10322
+ @media (prefers-reduced-motion: reduce) {
10323
+ .crewlet-data-grid__th,
10324
+ .crewlet-data-grid__row {
10325
+ transition: none;
10326
+ }
10327
+ }
10328
+
10329
+ /* ---- A ROW IS A CARD ON A PHONE -----------------------------------------
10330
+ A GRID IS COLUMNS, AND A PHONE DOES NOT HAVE THEM: the grid clips (for its
10331
+ sticky head), so the columns past the edge were cut off with nothing to
10332
+ scroll to, and a sideways scroller resolves every flexible track to zero. So
10333
+ the head goes and each cell draws its own name beside its value
10334
+ (`data-label`); the subgrid chain is unwound to blocks and each cell is a
10335
+ flex line, label then value. A cell with nothing in it is no line
10336
+ (`:empty`), and a cell that draws a marked absence has content and stays.
10337
+ The sort is in the application's state, so a sorted list still arrives
10338
+ sorted. */
10339
+ @media (width < 640px) {
10340
+ .crewlet-data-grid {
10341
+ display: block;
10342
+ }
10343
+
10344
+ .crewlet-data-grid__head {
10345
+ display: none;
10346
+ }
10347
+
10348
+ .crewlet-data-grid__body,
10349
+ .crewlet-data-grid__band {
10350
+ display: block;
10351
+ }
10352
+
10353
+ .crewlet-data-grid__row {
10354
+ display: block;
10355
+ padding: var(--spacing-2) var(--spacing-3);
10356
+ min-height: 0;
10357
+ }
10358
+
10359
+ /* A FIXED BASIS lines the names up without a track, and the name wraps
10360
+ inside it rather than pushing its value past every other card line. */
10361
+ .crewlet-data-grid__cell {
10362
+ display: flex;
10363
+ align-items: baseline;
10364
+ gap: var(--spacing-3);
10365
+ padding: 1px 0;
10366
+ min-width: 0;
10367
+ }
10368
+
10369
+ .crewlet-data-grid__cell:empty {
10370
+ display: none;
10371
+ }
10372
+
10373
+ .crewlet-data-grid__cell[data-label]::before {
10374
+ content: attr(data-label);
10375
+ flex: 0 0 7rem;
10376
+ overflow-wrap: anywhere;
10377
+ font-size: var(--font-size-2xs);
10378
+ text-transform: uppercase;
10379
+ letter-spacing: var(--font-letter-spacing-wide);
10380
+ color: var(--color-text-tertiary);
10381
+ }
10382
+
10383
+ /* `shrink` and `right` are column shapes, and there are no columns here. */
10384
+ .crewlet-data-grid__cell--shrink,
10385
+ .crewlet-data-grid__cell--right {
10386
+ white-space: normal;
10387
+ justify-content: flex-start;
10388
+ }
10389
+
10390
+ .crewlet-data-grid__cell .crewlet-data-grid__truncate {
10391
+ white-space: normal;
10392
+ overflow: visible;
10393
+ text-overflow: clip;
10394
+ overflow-wrap: anywhere;
10395
+ }
10396
+
10397
+ /* ---- THE COMPACT ROW (`phoneRows="compact"`) ---------------------------
10398
+ TWO LINES, NO LABELS: what the row is, then its marks. One flex run that
10399
+ breaks once: the lead cells first, a zero-height full-width `::after`
10400
+ between them and the rest, then every other cell in column order. */
10401
+ .crewlet-data-grid[data-phone-rows='compact'] .crewlet-data-grid__row {
10402
+ display: flex;
10403
+ flex-wrap: wrap;
10404
+ align-items: center;
10405
+ gap: var(--spacing-1) var(--spacing-2);
10406
+ }
10407
+
10408
+ .crewlet-data-grid[data-phone-rows='compact'] .crewlet-data-grid__row::after {
10409
+ content: '';
10410
+ order: 1;
10411
+ flex-basis: 100%;
10412
+ height: 0;
10413
+ }
10414
+
10415
+ .crewlet-data-grid[data-phone-rows='compact'] .crewlet-data-grid__cell {
10416
+ order: 2;
10417
+ padding: 0;
10418
+ align-items: center;
10419
+ gap: var(--spacing-1);
10420
+ }
10421
+
10422
+ .crewlet-data-grid[data-phone-rows='compact'] .crewlet-data-grid__cell[data-lead] {
10423
+ order: 0;
10424
+ }
10425
+
10426
+ /* The title takes the rest of the first line, beside the key. */
10427
+ .crewlet-data-grid[data-phone-rows='compact']
10428
+ .crewlet-data-grid__cell[data-lead]:not(.crewlet-data-grid__cell--shrink) {
10429
+ flex: 1 1 0;
10430
+ min-width: 0;
10431
+ font-weight: var(--font-weight-medium);
10432
+ }
10433
+
10434
+ .crewlet-data-grid[data-phone-rows='compact'] .crewlet-data-grid__cell[data-label]::before {
10435
+ content: none;
10436
+ }
10437
+
10438
+ .crewlet-data-grid[data-phone-rows='compact'] .crewlet-data-grid__cell[data-phone-omit] {
10439
+ display: none;
10440
+ }
9793
10441
  }
9794
10442
 
9795
10443
 
@@ -17454,6 +18102,25 @@ button.crewlet-finding-list__row:focus-visible {
17454
18102
  }
17455
18103
 
17456
18104
 
18105
+ /* LockedLabel-VQEGEB7G.css */
18106
+ /*
18107
+ * LockedLabel: a place's words with the key after them. The words keep their
18108
+ * own ink and size; the key takes the quiet step, a step closer to the words
18109
+ * than the words are to anything else.
18110
+ */
18111
+ .crewlet-locked-label {
18112
+ display: inline-flex;
18113
+ align-items: center;
18114
+ gap: var(--spacing-1);
18115
+ min-width: 0;
18116
+ }
18117
+
18118
+ .crewlet-locked-label__key {
18119
+ flex: none;
18120
+ color: var(--color-text-tertiary);
18121
+ }
18122
+
18123
+
17457
18124
  /* MarkdownEditor-WOKV7CLK.css */
17458
18125
  /*
17459
18126
  * Writing markdown (MarkdownEditor.tsx): the bar, the source or its preview,
@@ -20181,6 +20848,21 @@ button.crewlet-finding-list__row:focus-visible {
20181
20848
  }
20182
20849
 
20183
20850
 
20851
+ /* PageNote-RHLXH3ML.css */
20852
+ /*
20853
+ * PageNote: the screen's one quiet sentence. No word alone on its last line
20854
+ * (`pretty`), which reads as a sentence that stopped rather than one that
20855
+ * ended. No margin of its own: the column it stands in sets the gap.
20856
+ */
20857
+ .crewlet-page-note {
20858
+ margin: 0;
20859
+ max-width: var(--size-measure);
20860
+ font-size: var(--font-size-compact);
20861
+ color: var(--color-text-tertiary);
20862
+ text-wrap: pretty;
20863
+ }
20864
+
20865
+
20184
20866
  /* PeopleRail-SZGHZXVT.css */
20185
20867
  /* PeopleRail: a raised column of everybody present, one row a person, the
20186
20868
  name over what they are doing and the controls at the row's end. */
@@ -21221,6 +21903,105 @@ button.crewlet-presence-stack__member:focus-visible {
21221
21903
  }
21222
21904
 
21223
21905
 
21906
+ /* PropertyList-SCYM66LL.css */
21907
+ /*
21908
+ * An object's properties, in sections, on one grid.
21909
+ *
21910
+ * ONE TERM COLUMN DOWN THE WHOLE LIST. Every section is a description list of
21911
+ * its own, laid out as a SUBGRID of this one, so its terms and details sit on
21912
+ * this grid's two tracks and every section's labels start and end where the
21913
+ * others' do. The term track is the description list's own measure,
21914
+ * `--crewlet-description-list-term`, so a page that sets it once lines a list
21915
+ * of properties up with every key-value card on it. Unset, it is the rail's
21916
+ * own: as wide as the longest label, and never under 92px, which a one-word
21917
+ * label ("Due") would otherwise shrink the column to.
21918
+ *
21919
+ * SIDE BY SIDE AT EVERY WIDTH. A list of properties sits in a rail or a card
21920
+ * of its own width, so the window's width says nothing about the room it has;
21921
+ * the description list's narrow step (term over detail) is cancelled below.
21922
+ */
21923
+
21924
+ .crewlet-property-list {
21925
+ display: grid;
21926
+ grid-template-columns: var(--crewlet-description-list-term, minmax(92px, max-content)) minmax(0, 1fr);
21927
+ gap: var(--spacing-2) var(--spacing-3);
21928
+ align-items: baseline;
21929
+ min-width: 0;
21930
+ font-size: var(--font-size-compact);
21931
+ }
21932
+
21933
+ /* Two classes, so the description list's own track and narrow step (one
21934
+ class, in a media query) give way to the subgrid at every width. */
21935
+ .crewlet-property-list > .crewlet-property-list__group {
21936
+ grid-column: 1 / -1;
21937
+ grid-template-columns: subgrid;
21938
+ gap: inherit;
21939
+ font-size: inherit;
21940
+ }
21941
+
21942
+ .crewlet-property-list .crewlet-description-list__detail {
21943
+ margin-bottom: 0;
21944
+ }
21945
+
21946
+ /* THE LABEL IS AN IDENTIFIER (an environment variable's name, a tag's key),
21947
+ set in the mono face; a word stays in the list's own. */
21948
+ .crewlet-property-list__identifier {
21949
+ font-family: var(--font-family-mono);
21950
+ }
21951
+
21952
+ /*
21953
+ * A SECTION'S HEADING, with a hairline above it that separates it from the
21954
+ * section before. The list's FIRST heading has nothing to be separated from,
21955
+ * so it alone loses the hairline; a list that opens with rows of no section
21956
+ * keeps it on its first heading, which has rows above it.
21957
+ */
21958
+ .crewlet-property-list__heading {
21959
+ grid-column: 1 / -1;
21960
+ margin-top: var(--spacing-2);
21961
+ padding-top: var(--spacing-2);
21962
+ border-top: 1px solid var(--color-border-default);
21963
+ color: var(--color-text-tertiary);
21964
+ }
21965
+
21966
+ .crewlet-property-list__heading:first-child {
21967
+ margin-top: 0;
21968
+ padding-top: 0;
21969
+ border-top: none;
21970
+ }
21971
+
21972
+ .crewlet-property-list--eyebrow .crewlet-property-list__heading {
21973
+ font-size: var(--font-size-2xs);
21974
+ font-weight: var(--font-weight-medium);
21975
+ letter-spacing: var(--font-letter-spacing-wide);
21976
+ text-transform: uppercase;
21977
+ }
21978
+
21979
+ .crewlet-property-list--sentence .crewlet-property-list__heading {
21980
+ font-size: var(--font-size-xs);
21981
+ font-weight: var(--font-weight-medium);
21982
+ }
21983
+
21984
+ /* A SECTION NOBODY HAS FILLED IN, said once across both tracks in the words
21985
+ its caller wrote. It is a sentence a reader has to read, so it takes the
21986
+ tertiary rung, never the muted one (a floor for a mark). */
21987
+ .crewlet-property-list__empty {
21988
+ grid-column: 1 / -1;
21989
+ margin: 0;
21990
+ font-size: var(--font-size-xs);
21991
+ color: var(--color-text-tertiary);
21992
+ }
21993
+
21994
+ /* WHO SET IT, under the value rather than beside it: the value is what the
21995
+ reader came for. A line of its own, so a long actor name cannot push the
21996
+ value out of its track. */
21997
+ .crewlet-property-list__set-by {
21998
+ display: block;
21999
+ margin-top: 2px;
22000
+ font-size: var(--font-size-2xs);
22001
+ color: var(--color-text-tertiary);
22002
+ }
22003
+
22004
+
21224
22005
  /* Prose-BTXNFT2Q.css */
21225
22006
  /*
21226
22007
  * Natural language: the proportional face, real leading, a bounded measure.
@@ -21542,6 +22323,15 @@ button.crewlet-presence-stack__member:focus-visible {
21542
22323
  }
21543
22324
 
21544
22325
 
22326
+ /* RelatedRow-2FVS6QQA.css */
22327
+ /* RelatedRow: the glyphs in the quiet ink; everything else is the kit's card. */
22328
+ .crewlet-related-row__glyph {
22329
+ display: inline-flex;
22330
+ flex: none;
22331
+ color: var(--color-text-tertiary);
22332
+ }
22333
+
22334
+
21545
22335
  /* RelativeTime-EBAQPGO2.css */
21546
22336
  /*
21547
22337
  * A relative time is text, so it takes the register around it. Its one rule is
@@ -22326,6 +23116,173 @@ button.crewlet-presence-stack__member:focus-visible {
22326
23116
  }
22327
23117
 
22328
23118
 
23119
+ /* SectionFrame-M62UUVFQ.css */
23120
+ /*
23121
+ * SectionFrame: a column of sections beside the screen, and the one-row
23122
+ * picker it folds to.
23123
+ */
23124
+
23125
+ /* THE FRAME TAKES THE CONTENT COLUMN'S PADDING BACK and gives it to the body,
23126
+ so the column is flush with the sheet and the section keeps the inset. */
23127
+ .crewlet-app-shell__content:has(> .crewlet-section-frame) {
23128
+ min-height: 100%;
23129
+ padding: 0;
23130
+ }
23131
+
23132
+ .crewlet-section-frame {
23133
+ display: grid;
23134
+ flex: 1 1 auto;
23135
+ grid-template-columns: var(--crewlet-section-frame-column) minmax(0, 1fr);
23136
+ min-height: 100%;
23137
+ }
23138
+
23139
+ /*
23140
+ * AS TALL AS THE VIEW, NEVER AS THE GRID. A sticky box moves only inside its
23141
+ * grid area, which the section beside it makes as tall as its content; sized
23142
+ * against that area the column was exactly as tall as the section, had
23143
+ * nowhere to stick, and a wheel over a long section carried the list off the
23144
+ * top. At the view's height (`100cqb`: the shell's scroller is a size
23145
+ * container) it sticks for the whole scroll and a long list scrolls in itself.
23146
+ *
23147
+ * IT KEEPS THE WHEEL AT ITS ENDS. A box whose bottom is below the fold traps
23148
+ * the wheel; this one is exactly the view and always all on screen, so what
23149
+ * chaining would do is move the section beside it at the list's end, which
23150
+ * is not what the pointer is over.
23151
+ */
23152
+ .crewlet-section-frame__nav {
23153
+ position: sticky;
23154
+ top: 0;
23155
+ align-self: start;
23156
+ height: 100cqb;
23157
+ overflow-y: auto;
23158
+ overscroll-behavior: contain;
23159
+ padding: var(--spacing-4) 0;
23160
+ border-right: 1px solid var(--color-border-default);
23161
+ }
23162
+
23163
+ .crewlet-section-frame__body {
23164
+ display: flex;
23165
+ flex-direction: column;
23166
+ gap: var(--spacing-5);
23167
+ min-width: 0;
23168
+ padding: var(--spacing-5) var(--spacing-5) var(--spacing-10);
23169
+ }
23170
+
23171
+ /* BESIDE THE SECTION there is room for the whole list: no toggle, and the
23172
+ list is always drawn. */
23173
+ .crewlet-section-frame__toggle {
23174
+ display: none;
23175
+ }
23176
+
23177
+ /*
23178
+ * FOLDED: one pane, the picker above the section. The picker's row is its
23179
+ * own height and the section takes the rest: two `auto` rows split a short
23180
+ * section's spare height and opened a band of nothing between the picker
23181
+ * and the section it names.
23182
+ */
23183
+ .crewlet-section-frame[data-folded] {
23184
+ grid-template-columns: minmax(0, 1fr);
23185
+ grid-template-rows: auto 1fr;
23186
+ }
23187
+
23188
+ /* IN THE FLOW, as tall as it is, on the section's own gutter: the list it
23189
+ unfolds is part of the page rather than a pane of its own. */
23190
+ .crewlet-section-frame[data-folded] > .crewlet-section-frame__nav {
23191
+ position: static;
23192
+ height: auto;
23193
+ overflow-y: visible;
23194
+ padding: var(--spacing-2) var(--spacing-5);
23195
+ border-right: none;
23196
+ border-bottom: 1px solid var(--color-border-default);
23197
+ }
23198
+
23199
+ /* ONE ROW NAMING WHERE THE READER IS, which unfolds the list. Its glyph and
23200
+ name stand over the glyphs and names of the rows: the rows' own inset,
23201
+ less the toggle's border. */
23202
+ .crewlet-section-frame[data-folded] .crewlet-section-frame__toggle {
23203
+ display: flex;
23204
+ align-items: center;
23205
+ gap: var(--spacing-2);
23206
+ width: 100%;
23207
+ min-height: var(--size-target-min);
23208
+ padding: 0 calc(var(--size-nav-row-pad) - 1px);
23209
+ border: 1px solid var(--color-border-default);
23210
+ border-radius: var(--radius-sm);
23211
+ background: var(--color-surface-elevated);
23212
+ color: var(--color-text-primary);
23213
+ font: inherit;
23214
+ font-weight: var(--font-weight-medium);
23215
+ text-align: left;
23216
+ cursor: pointer;
23217
+ }
23218
+
23219
+ .crewlet-section-frame[data-folded] .crewlet-section-frame__toggle:hover {
23220
+ background: var(--color-surface-hover);
23221
+ }
23222
+
23223
+ /* INSIDE ITS OWN EDGE, as every control that draws one rings. */
23224
+ .crewlet-section-frame__toggle:focus-visible {
23225
+ outline: 2px solid var(--color-focus);
23226
+ outline-offset: var(--size-focus-ring-inset-offset);
23227
+ }
23228
+
23229
+ .crewlet-section-frame__toggle-icon {
23230
+ display: inline-flex;
23231
+ flex: none;
23232
+ }
23233
+
23234
+ .crewlet-section-frame__toggle-name {
23235
+ flex: 1 1 auto;
23236
+ min-width: 0;
23237
+ overflow: hidden;
23238
+ text-overflow: ellipsis;
23239
+ white-space: nowrap;
23240
+ }
23241
+
23242
+ /* "Section ·" BEFORE THE NAME, in the quiet ink, so the row reads as a
23243
+ control holding the other sections rather than as the page's title. */
23244
+ .crewlet-section-frame__toggle-prefix {
23245
+ color: var(--color-text-tertiary);
23246
+ font-weight: var(--font-weight-regular);
23247
+ }
23248
+
23249
+ .crewlet-section-frame__chevron {
23250
+ flex: none;
23251
+ color: var(--color-text-tertiary);
23252
+ }
23253
+
23254
+ .crewlet-section-frame__nav[data-open] .crewlet-section-frame__chevron {
23255
+ transform: rotate(180deg);
23256
+ }
23257
+
23258
+ .crewlet-section-frame[data-folded] .crewlet-section-frame__nav:not([data-open]) .crewlet-section-frame__list {
23259
+ display: none;
23260
+ }
23261
+
23262
+ .crewlet-section-frame[data-folded] .crewlet-section-frame__nav[data-open] .crewlet-section-frame__list {
23263
+ padding-top: var(--spacing-2);
23264
+ }
23265
+
23266
+ /* THE LIST TAKES NO GUTTER OF ITS OWN inside the folded picker, which is
23267
+ inset already: with the rail's gutter on top, its glyphs sat 11px right of
23268
+ the toggle's. */
23269
+ .crewlet-section-frame[data-folded] .crewlet-section-frame__list > .crewlet-sidebar-nav {
23270
+ padding-inline: 0;
23271
+ }
23272
+
23273
+ /* A PHONE'S ONE GUTTER: the section and the picker start where every other
23274
+ screen's content does. */
23275
+ @media (width < 640px) {
23276
+ .crewlet-section-frame__body {
23277
+ padding: var(--spacing-4) var(--spacing-4) var(--spacing-9);
23278
+ }
23279
+
23280
+ .crewlet-section-frame[data-folded] > .crewlet-section-frame__nav {
23281
+ padding-inline: var(--spacing-4);
23282
+ }
23283
+ }
23284
+
23285
+
22329
23286
  /* SegmentedControl-B7XCUOML.css */
22330
23287
  /*
22331
23288
  * SegmentedControl: the pill row, drawn with the Tabs classes.
@@ -24383,7 +25340,7 @@ svg.crewlet-select__chevron {
24383
25340
  }
24384
25341
 
24385
25342
 
24386
- /* SidebarNav-7SGUZYKK.css */
25343
+ /* SidebarNav-YI74SPDC.css */
24387
25344
  /*
24388
25345
  * The rail's navigation.
24389
25346
  *
@@ -24813,6 +25770,16 @@ svg.crewlet-select__chevron {
24813
25770
  }
24814
25771
  }
24815
25772
 
25773
+ /*
25774
+ * A GROUP THE READER HOLDS NONE OF: the key once, after its label (see
25775
+ * `NavGroup`'s `locked`), and its resting rows in the quiet ink, so a closed
25776
+ * column reads as closed at a glance without a key on every row. A pointed
25777
+ * row and the reader's own still lift to the primary step, as every row does.
25778
+ */
25779
+ .crewlet-nav-group--locked .crewlet-nav-item__row:not([aria-current]):not(:hover) {
25780
+ color: var(--color-text-tertiary);
25781
+ }
25782
+
24816
25783
 
24817
25784
  /* Skeleton-V735HRGM.css */
24818
25785
  /*
@@ -27609,7 +28576,7 @@ b.crewlet-switcher__match {
27609
28576
  }
27610
28577
 
27611
28578
 
27612
- /* Tabs-WIF7457H.css */
28579
+ /* Tabs-S7F4RWAN.css */
27613
28580
  /*
27614
28581
  * The pill register: Tabs and SegmentedControl.
27615
28582
  *
@@ -28012,6 +28979,83 @@ b.crewlet-switcher__match {
28012
28979
  display: contents;
28013
28980
  }
28014
28981
 
28982
+ /* ─── Fold (overflow: menu) ───────────────────────────────────── */
28983
+ /*
28984
+ * THE ROW NEVER SCROLLS: what does not fit has already left it for "More".
28985
+ * A scroll with its bar hidden cut a whole tab off at a phone's edge with
28986
+ * nothing to say it was there, and a fade at the edge is too quiet to read as
28987
+ * "there is more"; a menu that says More is not.
28988
+ */
28989
+ .crewlet-tabs--fold {
28990
+ position: relative;
28991
+ min-width: 0;
28992
+ overflow: visible;
28993
+ }
28994
+
28995
+ /*
28996
+ * A FOLDED ITEM STAYS IN THE DOCUMENT, out of the flow and invisible, so it
28997
+ * can be measured again when the row grows. Pinned to the row's start, inside
28998
+ * it, so it can never widen the page. A tab, "More" with nothing in it, and a
28999
+ * note with no room alike.
29000
+ */
29001
+ .crewlet-tabs--fold > .crewlet-tabs__tab.is-folded,
29002
+ .crewlet-tabs__more.is-folded,
29003
+ .crewlet-tabs__note.is-folded {
29004
+ position: absolute;
29005
+ inset-block-start: 0;
29006
+ inset-inline-start: 0;
29007
+ visibility: hidden;
29008
+ pointer-events: none;
29009
+ }
29010
+
29011
+ /* "More" is the quiet menu button, centred on the tabs' line. */
29012
+ .crewlet-tabs__more {
29013
+ display: inline-flex;
29014
+ flex: none;
29015
+ align-items: center;
29016
+ }
29017
+
29018
+ /* The note sits at the row's far end, a sentence about every tab and never
29019
+ one of them. */
29020
+ .crewlet-tabs__note {
29021
+ flex: none;
29022
+ align-self: center;
29023
+ margin-inline-start: auto;
29024
+ font-size: var(--font-size-xs);
29025
+ color: var(--color-text-tertiary);
29026
+ white-space: nowrap;
29027
+ }
29028
+
29029
+ .crewlet-tabs__trailing {
29030
+ display: inline-flex;
29031
+ flex: none;
29032
+ align-items: center;
29033
+ }
29034
+
29035
+ /*
29036
+ * A TAB LIST HOLDS TABS ALONE, so its "More" stands beside it in a box. The
29037
+ * row is as wide as the tabs it draws, and the underline's rule is the box's,
29038
+ * painted on its last pixel row (the one the row's own border sits on), so
29039
+ * it runs on under "More" to the edge.
29040
+ */
29041
+ .crewlet-tabs-fold {
29042
+ position: relative;
29043
+ display: flex;
29044
+ align-items: stretch;
29045
+ gap: var(--spacing-2);
29046
+ min-width: 0;
29047
+ }
29048
+
29049
+ .crewlet-tabs-fold > .crewlet-tabs {
29050
+ flex: 0 1 auto;
29051
+ width: auto;
29052
+ min-width: 0;
29053
+ }
29054
+
29055
+ .crewlet-tabs-fold--underline {
29056
+ box-shadow: inset 0 -1px 0 var(--color-border-default);
29057
+ }
29058
+
28015
29059
  /*
28016
29060
  * The slider ARRIVES rather than travels, and a chip changes without a fade.
28017
29061
  * The indicator still moves; what stops is the animation between the two