@atelic-action/ui 0.17.2 → 1.0.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 (184) hide show
  1. package/README.md +428 -44
  2. package/bin/atelic-check-base-path.ts +5 -0
  3. package/bin/atelic-clean-sitemap.ts +5 -0
  4. package/bin/atelic-contact-canary.ts +5 -0
  5. package/bin/atelic-print-sheets.sh +1 -1
  6. package/bin/atelic-seal-document.mjs +1 -1
  7. package/bin/atelic-serve-static.ts +1 -1
  8. package/dist/gate/index.d.ts +1 -1
  9. package/dist/gate/index.js +1 -1
  10. package/dist/gate/middleware.d.ts +4 -1
  11. package/dist/gate/middleware.js +14 -5
  12. package/dist/gate/wall.d.ts +25 -0
  13. package/dist/gate/wall.js +41 -2
  14. package/dist/routing/basePath.d.ts +24 -0
  15. package/dist/routing/basePath.js +54 -0
  16. package/dist/vite/index.d.ts +3 -2
  17. package/dist/vite/index.js +3 -2
  18. package/dist/vite/marketing-config.d.ts +50 -0
  19. package/dist/vite/marketing-config.js +83 -0
  20. package/package.json +164 -5
  21. package/src/app/AppProvider.tsx +41 -0
  22. package/src/app/AuthGuard.tsx +27 -0
  23. package/src/app/CardErrorBoundary.tsx +39 -0
  24. package/src/app/ErrorFallback.tsx +39 -0
  25. package/src/app/GoogleGlyph.tsx +22 -0
  26. package/src/app/config.ts +54 -0
  27. package/src/app/configure.ts +18 -0
  28. package/src/app/context/AppContext.tsx +52 -0
  29. package/src/app/context/SidebarContext.tsx +124 -0
  30. package/src/app/context/UserContext.tsx +139 -0
  31. package/src/app/hooks/useDebounce.ts +12 -0
  32. package/src/app/hooks/useIsDesktop.ts +31 -0
  33. package/src/app/hooks/useWakeLock.ts +49 -0
  34. package/src/app/index.ts +64 -0
  35. package/src/app/layout/ActionButton.tsx +67 -0
  36. package/src/app/layout/AppLayout.tsx +110 -0
  37. package/src/app/layout/AppPage.tsx +268 -0
  38. package/src/app/layout/Breadcrumbs.tsx +57 -0
  39. package/src/app/layout/DesktopRail.tsx +168 -0
  40. package/src/app/layout/FormActionButtons.tsx +69 -0
  41. package/src/app/layout/MobileMenu.tsx +156 -0
  42. package/src/app/layout/MobileTabBar.tsx +43 -0
  43. package/src/app/layout/PageError.tsx +30 -0
  44. package/src/app/layout/PageSkeleton.tsx +65 -0
  45. package/src/app/layout/SectionCards.tsx +33 -0
  46. package/src/app/layout/UserMenu.tsx +104 -0
  47. package/src/app/layout/identity.ts +22 -0
  48. package/src/app/layout/index.ts +20 -0
  49. package/src/app/layout/nav.ts +52 -0
  50. package/src/app/lib/dates.ts +57 -0
  51. package/src/app/lib/env.ts +37 -0
  52. package/src/app/lib/format.ts +61 -0
  53. package/src/app/lib/http.ts +205 -0
  54. package/src/app/lib/lastAuth.ts +45 -0
  55. package/src/app/lib/oauth.ts +32 -0
  56. package/src/app/lib/publicRoutes.ts +33 -0
  57. package/src/app/lib/queryClient.ts +38 -0
  58. package/src/app/lib/search.ts +17 -0
  59. package/src/app/lib/session.ts +36 -0
  60. package/src/app/lib/tokenRefresh.ts +137 -0
  61. package/src/app/lib/transformKeys.ts +60 -0
  62. package/src/app/lib/units.ts +228 -0
  63. package/src/app/lib/unwrap.ts +48 -0
  64. package/src/app/lib/utils.ts +10 -0
  65. package/src/app/stores/authStore.ts +80 -0
  66. package/src/app/stores/storage.ts +40 -0
  67. package/src/app/stores/unitsStore.ts +54 -0
  68. package/src/app/types/index.ts +72 -0
  69. package/src/app/types/query.ts +11 -0
  70. package/src/app/ui/accordion.tsx +54 -0
  71. package/src/app/ui/alert-dialog.tsx +114 -0
  72. package/src/app/ui/alert.tsx +49 -0
  73. package/src/app/ui/avatar.tsx +45 -0
  74. package/src/app/ui/badge-list.tsx +51 -0
  75. package/src/app/ui/badge.tsx +33 -0
  76. package/src/app/ui/button.tsx +49 -0
  77. package/src/app/ui/callout.tsx +22 -0
  78. package/src/app/ui/card.tsx +55 -0
  79. package/src/app/ui/checkbox.tsx +26 -0
  80. package/src/app/ui/clear-button.tsx +42 -0
  81. package/src/app/ui/command.tsx +140 -0
  82. package/src/app/ui/country-dropdown.tsx +184 -0
  83. package/src/app/ui/dialog.tsx +104 -0
  84. package/src/app/ui/dropdown-menu.tsx +185 -0
  85. package/src/app/ui/form.tsx +172 -0
  86. package/src/app/ui/index.ts +36 -0
  87. package/src/app/ui/input.tsx +22 -0
  88. package/src/app/ui/label.tsx +19 -0
  89. package/src/app/ui/option-select.tsx +56 -0
  90. package/src/app/ui/pagination.tsx +90 -0
  91. package/src/app/ui/popover.tsx +29 -0
  92. package/src/app/ui/progress.tsx +25 -0
  93. package/src/app/ui/search-input.tsx +63 -0
  94. package/src/app/ui/select.tsx +151 -0
  95. package/src/app/ui/separator.tsx +24 -0
  96. package/src/app/ui/sheet.tsx +119 -0
  97. package/src/app/ui/slider.tsx +23 -0
  98. package/src/app/ui/switch.tsx +27 -0
  99. package/src/app/ui/textarea.tsx +21 -0
  100. package/src/app/ui/tooltip.tsx +32 -0
  101. package/src/artifact/ArtifactShell.tsx +2 -2
  102. package/src/artifact/Gate.tsx +2 -2
  103. package/src/artifact/Writeup.tsx +7 -7
  104. package/src/chrome/SiteShell.tsx +141 -0
  105. package/src/chrome/index.ts +2 -0
  106. package/src/components/Disclosure.tsx +80 -14
  107. package/src/components/GateLogin.tsx +1 -1
  108. package/src/components/Watermark.tsx +1 -1
  109. package/src/components/index.ts +6 -2
  110. package/src/gate/index.ts +1 -1
  111. package/src/gate/middleware.ts +17 -6
  112. package/src/gate/wall.ts +60 -2
  113. package/src/lib/basePathAudit.ts +96 -0
  114. package/src/lib/displayDate.ts +25 -0
  115. package/src/lib/honeypot.ts +11 -0
  116. package/src/lib/hours.ts +28 -0
  117. package/src/lib/sitemap.ts +34 -0
  118. package/src/lib/trackEvent.ts +26 -0
  119. package/src/lib/useOpenHeight.ts +28 -0
  120. package/src/primitives/Button.tsx +3 -1
  121. package/src/primitives/Chip.tsx +3 -1
  122. package/src/primitives/ImageFrame.tsx +48 -0
  123. package/src/primitives/ProseBlocks.tsx +67 -0
  124. package/src/primitives/QuoteCard.tsx +20 -0
  125. package/src/primitives/StarRow.tsx +37 -0
  126. package/src/primitives/TickList.tsx +24 -0
  127. package/src/primitives/index.ts +5 -0
  128. package/src/routing/BasePathProvider.tsx +47 -0
  129. package/src/routing/basePath.ts +57 -0
  130. package/src/routing/index.ts +8 -0
  131. package/src/scripts/check-base-path.ts +130 -0
  132. package/src/scripts/clean-sitemap.ts +27 -0
  133. package/src/scripts/contact-canary.ts +98 -0
  134. package/src/scripts/serve-static.ts +29 -3
  135. package/src/sections/BlogIndex.tsx +57 -0
  136. package/src/sections/BlogPost.tsx +65 -0
  137. package/src/sections/CTABanner.tsx +93 -0
  138. package/src/sections/CTASection.tsx +60 -0
  139. package/src/sections/ComparisonTable.tsx +114 -0
  140. package/src/sections/ContactForm.tsx +163 -0
  141. package/src/sections/ContactInfoCard.tsx +92 -0
  142. package/src/sections/CredentialList.tsx +28 -0
  143. package/src/sections/DeviceShowcase.tsx +39 -0
  144. package/src/sections/ExpandList.tsx +58 -0
  145. package/src/sections/FAQBrowser.tsx +283 -0
  146. package/src/sections/FeatureDetail.tsx +60 -0
  147. package/src/sections/FeatureGrid.tsx +83 -0
  148. package/src/sections/Gallery.tsx +84 -0
  149. package/src/sections/Hero.tsx +110 -0
  150. package/src/sections/HoursTable.tsx +23 -0
  151. package/src/sections/JumpRail.tsx +35 -0
  152. package/src/sections/LegalPage.tsx +43 -0
  153. package/src/sections/LocationSection.tsx +66 -0
  154. package/src/sections/Locations.tsx +71 -0
  155. package/src/sections/LogoMarquee.tsx +27 -0
  156. package/src/sections/MapEmbed.tsx +75 -0
  157. package/src/sections/MediaBand.tsx +20 -0
  158. package/src/sections/MenuList.tsx +44 -0
  159. package/src/sections/PageHero.tsx +25 -0
  160. package/src/sections/PressQuotes.tsx +51 -0
  161. package/src/sections/PricingBand.tsx +43 -0
  162. package/src/sections/PricingCard.tsx +36 -0
  163. package/src/sections/ProcessSteps.tsx +45 -0
  164. package/src/sections/ProfileCards.tsx +73 -0
  165. package/src/sections/RevealSlider.tsx +156 -0
  166. package/src/sections/ReviewCarousel.tsx +223 -0
  167. package/src/sections/ReviewWall.tsx +220 -0
  168. package/src/sections/SocialStrip.tsx +83 -0
  169. package/src/sections/SplitSection.tsx +56 -0
  170. package/src/sections/index.ts +76 -0
  171. package/src/sections/siteConfig.ts +201 -0
  172. package/src/styles/app.css +673 -0
  173. package/src/styles/artifact.css +472 -399
  174. package/src/styles/base.css +49 -47
  175. package/src/styles/chrome.css +71 -71
  176. package/src/styles/components.css +150 -140
  177. package/src/styles/gate.css +29 -29
  178. package/src/styles/primitives.css +190 -25
  179. package/src/styles/sections.css +2652 -0
  180. package/src/styles/star-rating.css +2 -2
  181. package/src/vite/index.ts +9 -2
  182. package/src/vite/marketing-config.ts +128 -0
  183. package/src/components/Collapsible.tsx +0 -43
  184. /package/src/scripts/{build-gate-payload.mjs → seal-document.mjs} +0 -0
@@ -4,11 +4,10 @@
4
4
  classes (.page-hero, .eyebrow, .lead, .btn) arrive unlayered and win, so
5
5
  these only fill in where a site does not style them.
6
6
 
7
- Every rule answers to either of two scopes. `.mkt` is a site's canvas,
8
- which base.css also resets headings, links, and buttons under.
9
- `.atelic-ui` is the same scope with no resets behind it, for an app that
10
- has its own base (Tailwind, shadcn) and wants only the components. The
11
- two weigh the same, so nothing a site already overrides changes.
7
+ Every rule answers to `.atelic-ui`, the one root class a consumer wears.
8
+ A site also imports base.css, which resets headings, links, and buttons
9
+ under the same class; an app with its own base (Tailwind, shadcn) imports
10
+ this sheet alone and gets the components with no resets behind them.
12
11
 
13
12
  Two tokens are read through names of the package's own first:
14
13
  `--ui-primary` and `--ui-card`, each falling back to `--primary` and
@@ -16,27 +15,27 @@
16
15
  `--primary` and `--card` hold something else (shadcn keeps bare HSL
17
16
  channels there) sets the `--ui-` names and leaves its own alone. */
18
17
  @layer atelic-ui {
19
- :is(.mkt, .atelic-ui) .not-found-hero {
18
+ .atelic-ui .not-found-hero {
20
19
  padding-top: calc(var(--nav-height, 72px) + clamp(40px, 7vw, 86px));
21
20
  padding-bottom: clamp(28px, 5vw, 60px);
22
21
  }
23
- :is(.mkt, .atelic-ui) .not-found-hero h1 {
22
+ .atelic-ui .not-found-hero h1 {
24
23
  margin: 16px 0 0;
25
24
  }
26
- :is(.mkt, .atelic-ui) .not-found-hero .lead {
25
+ .atelic-ui .not-found-hero .lead {
27
26
  margin-top: 22px;
28
27
  max-width: 56ch;
29
28
  }
30
- :is(.mkt, .atelic-ui) .not-found-links .cta-row,
31
- :is(.mkt, .atelic-ui) .not-found-closing .cta-row {
29
+ .atelic-ui .not-found-links .cta-row,
30
+ .atelic-ui .not-found-closing .cta-row {
32
31
  margin-top: 22px;
33
32
  }
34
33
 
35
34
  /* ---- Tones: the one palette this package carries, because good, a
36
35
  warning, and broken read green, amber, and red whatever the brand is.
37
- A site's theme may restate any of these on .mkt. A component sets
36
+ A site's theme may restate any of these on .atelic-ui. A component sets
38
37
  data-tone, and --tone, --tone-fill, and --tone-bg follow. ---- */
39
- :is(.mkt, .atelic-ui) {
38
+ .atelic-ui {
40
39
  --tone-good: #1b7f3b;
41
40
  --tone-good-fill: #37a35c;
42
41
  --tone-good-bg: #eaf6ee;
@@ -47,27 +46,27 @@
47
46
  --tone-bad-fill: #d9483f;
48
47
  --tone-bad-bg: #fdecea;
49
48
  }
50
- :is(.mkt, .atelic-ui) [data-tone="good"] {
49
+ .atelic-ui [data-tone="good"] {
51
50
  --tone: var(--tone-good);
52
51
  --tone-fill: var(--tone-good-fill);
53
52
  --tone-bg: var(--tone-good-bg);
54
53
  }
55
- :is(.mkt, .atelic-ui) [data-tone="warn"] {
54
+ .atelic-ui [data-tone="warn"] {
56
55
  --tone: var(--tone-warn);
57
56
  --tone-fill: var(--tone-warn-fill);
58
57
  --tone-bg: var(--tone-warn-bg);
59
58
  }
60
- :is(.mkt, .atelic-ui) [data-tone="bad"] {
59
+ .atelic-ui [data-tone="bad"] {
61
60
  --tone: var(--tone-bad);
62
61
  --tone-fill: var(--tone-bad-fill);
63
62
  --tone-bg: var(--tone-bad-bg);
64
63
  }
65
- :is(.mkt, .atelic-ui) [data-tone="info"] {
64
+ .atelic-ui [data-tone="info"] {
66
65
  --tone: var(--ui-primary, var(--primary));
67
66
  --tone-fill: var(--primary-bright);
68
67
  --tone-bg: var(--primary-tint);
69
68
  }
70
- :is(.mkt, .atelic-ui) [data-tone="muted"] {
69
+ .atelic-ui [data-tone="muted"] {
71
70
  --tone: var(--neutral-500);
72
71
  --tone-fill: var(--neutral-200);
73
72
  --tone-bg: var(--surface-alt);
@@ -75,20 +74,20 @@
75
74
 
76
75
  /* ---- StatRow: large figures, each over what it counts, its period,
77
76
  and its comparisons ---- */
78
- :is(.mkt, .atelic-ui) .stat-row {
77
+ .atelic-ui .stat-row {
79
78
  display: grid;
80
79
  gap: 24px;
81
80
  grid-template-columns: repeat(2, minmax(0, 1fr));
82
81
  }
83
82
  @media (min-width: 760px) {
84
- :is(.mkt, .atelic-ui) .stat-row {
83
+ .atelic-ui .stat-row {
85
84
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
86
85
  }
87
86
  }
88
- :is(.mkt, .atelic-ui) .stat-row.is-center .stat {
87
+ .atelic-ui .stat-row.is-center .stat {
89
88
  text-align: center;
90
89
  }
91
- :is(.mkt, .atelic-ui) .stat .num {
90
+ .atelic-ui .stat .num {
92
91
  display: flex;
93
92
  align-items: center;
94
93
  gap: 0.12em;
@@ -99,26 +98,26 @@
99
98
  line-height: 1;
100
99
  font-variant-numeric: tabular-nums;
101
100
  }
102
- :is(.mkt, .atelic-ui) .stat-row.is-center .stat .num {
101
+ .atelic-ui .stat-row.is-center .stat .num {
103
102
  justify-content: center;
104
103
  }
105
- :is(.mkt, .atelic-ui) .stat-trend {
104
+ .atelic-ui .stat-trend {
106
105
  width: 0.8em;
107
106
  height: 0.8em;
108
107
  flex: none;
109
108
  }
110
- :is(.mkt, .atelic-ui) .stat .lbl {
109
+ .atelic-ui .stat .lbl {
111
110
  font-size: 0.95rem;
112
111
  font-weight: 650;
113
112
  color: var(--ink);
114
113
  margin-top: 8px;
115
114
  }
116
- :is(.mkt, .atelic-ui) .stat-period {
115
+ .atelic-ui .stat-period {
117
116
  margin-left: 0.5em;
118
117
  font-weight: 400;
119
118
  color: var(--neutral-500);
120
119
  }
121
- :is(.mkt, .atelic-ui) .stat-delta {
120
+ .atelic-ui .stat-delta {
122
121
  display: flex;
123
122
  flex-wrap: wrap;
124
123
  align-items: baseline;
@@ -129,26 +128,26 @@
129
128
  color: var(--neutral-500);
130
129
  font-variant-numeric: tabular-nums;
131
130
  }
132
- :is(.mkt, .atelic-ui) .stat-delta-change {
131
+ .atelic-ui .stat-delta-change {
133
132
  display: inline-flex;
134
133
  align-items: center;
135
134
  gap: 2px;
136
135
  font-weight: 700;
137
136
  color: var(--tone);
138
137
  }
139
- :is(.mkt, .atelic-ui) .stat-delta-change svg {
138
+ .atelic-ui .stat-delta-change svg {
140
139
  align-self: center;
141
140
  }
142
- :is(.mkt, .atelic-ui) .stat-delta-basis {
141
+ .atelic-ui .stat-delta-basis {
143
142
  text-decoration: none;
144
143
  }
145
- :is(.mkt, .atelic-ui) .stat .note {
144
+ .atelic-ui .stat .note {
146
145
  font-size: 0.8rem;
147
146
  color: var(--neutral-500);
148
147
  margin-top: 4px;
149
148
  }
150
149
 
151
- :is(.mkt, .atelic-ui) .stat-unit {
150
+ .atelic-ui .stat-unit {
152
151
  margin-left: 0.2em;
153
152
  font-size: 0.4em;
154
153
  font-weight: 500;
@@ -159,20 +158,20 @@
159
158
  /* ---- StatRow, quiet: a glance row for a working page. A light figure in
160
159
  the text color over a small capitalized label, the stats divided by a
161
160
  hairline. `--stat-size` sets the figure. ---- */
162
- :is(.mkt, .atelic-ui) .stat-row.is-quiet {
161
+ .atelic-ui .stat-row.is-quiet {
163
162
  display: flex;
164
163
  gap: 0;
165
164
  }
166
- :is(.mkt, .atelic-ui) .stat-row.is-quiet .stat {
165
+ .atelic-ui .stat-row.is-quiet .stat {
167
166
  flex: 1;
168
167
  min-width: 64px;
169
168
  padding-right: 16px;
170
169
  }
171
- :is(.mkt, .atelic-ui) .stat-row.is-quiet .stat + .stat {
170
+ .atelic-ui .stat-row.is-quiet .stat + .stat {
172
171
  padding-left: 16px;
173
172
  border-left: 1px solid var(--neutral-200);
174
173
  }
175
- :is(.mkt, .atelic-ui) .stat-row.is-quiet .stat .num {
174
+ .atelic-ui .stat-row.is-quiet .stat .num {
176
175
  align-items: baseline;
177
176
  gap: 4px;
178
177
  font: 300 var(--stat-size, 28px) / 1 var(--font-sans);
@@ -181,11 +180,11 @@
181
180
  letter-spacing: -0.02em;
182
181
  color: var(--tone, var(--ink));
183
182
  }
184
- :is(.mkt, .atelic-ui) .stat-row.is-quiet .stat-unit {
183
+ .atelic-ui .stat-row.is-quiet .stat-unit {
185
184
  margin-left: 0;
186
185
  font: 500 12px / 1 var(--font-mono);
187
186
  }
188
- :is(.mkt, .atelic-ui) .stat-row.is-quiet .stat .lbl {
187
+ .atelic-ui .stat-row.is-quiet .stat .lbl {
189
188
  margin-top: 7px;
190
189
  font: 500 10px / 1.2 var(--font-sans);
191
190
  letter-spacing: 0.1em;
@@ -193,29 +192,30 @@
193
192
  color: var(--neutral-500);
194
193
  }
195
194
 
196
- /* ---- Disclosure: a section the page opens and closes. The toggle's
195
+ /* ---- Disclosure, controlled: an app's card, a section the page opens
196
+ and closes. The toggle's
197
197
  ::after covers the whole header row, so the meta and the chevron fold
198
198
  it too while staying out of its name. ---- */
199
- :is(.mkt, .atelic-ui) .disclosure {
199
+ .atelic-ui .disclosure {
200
200
  border: 1px solid var(--neutral-200);
201
201
  border-radius: 16px;
202
202
  background: var(--ui-card, var(--card));
203
203
  overflow: hidden;
204
204
  }
205
- :is(.mkt, .atelic-ui) .disclosure-head {
205
+ .atelic-ui .disclosure-head {
206
206
  position: relative;
207
207
  display: flex;
208
208
  align-items: center;
209
209
  gap: 10px;
210
210
  padding: 14px 18px;
211
211
  }
212
- :is(.mkt, .atelic-ui) .disclosure-title {
212
+ .atelic-ui .disclosure-title {
213
213
  display: flex;
214
214
  min-width: 0;
215
215
  margin: 0;
216
216
  font: inherit;
217
217
  }
218
- :is(.mkt, .atelic-ui) .disclosure-toggle {
218
+ .atelic-ui .disclosure-toggle {
219
219
  border: none;
220
220
  background: transparent;
221
221
  padding: 0;
@@ -225,117 +225,127 @@
225
225
  color: var(--ink);
226
226
  cursor: pointer;
227
227
  }
228
- :is(.mkt, .atelic-ui) .disclosure-toggle::after {
228
+ .atelic-ui .disclosure-toggle::after {
229
229
  content: "";
230
230
  position: absolute;
231
231
  inset: 0;
232
232
  }
233
- :is(.mkt, .atelic-ui) .disclosure-toggle:focus-visible {
233
+ .atelic-ui .disclosure-toggle:focus-visible {
234
234
  outline: none;
235
235
  }
236
- :is(.mkt, .atelic-ui) .disclosure-toggle:focus-visible::after {
236
+ .atelic-ui .disclosure-toggle:focus-visible::after {
237
237
  outline: 2px solid var(--disclosure-focus, var(--ink));
238
238
  outline-offset: -2px;
239
239
  border-radius: 15px;
240
240
  }
241
- :is(.mkt, .atelic-ui) .disclosure-meta {
241
+ .atelic-ui .disclosure-meta {
242
242
  display: inline-flex;
243
243
  align-items: center;
244
244
  color: var(--neutral-500);
245
245
  }
246
- :is(.mkt, .atelic-ui) .disclosure-chevron {
246
+ .atelic-ui .disclosure-chevron {
247
247
  margin-left: auto;
248
248
  flex-shrink: 0;
249
249
  color: var(--neutral-500);
250
250
  transition: transform 200ms ease;
251
251
  }
252
- :is(.mkt, .atelic-ui) .disclosure.is-open .disclosure-chevron {
252
+ .atelic-ui .disclosure.is-open > .disclosure-head > .disclosure-chevron {
253
253
  transform: rotate(180deg);
254
254
  }
255
- :is(.mkt, .atelic-ui) .disclosure-body {
255
+ .atelic-ui .disclosure-body {
256
256
  border-top: 1px solid var(--neutral-200);
257
257
  }
258
258
 
259
- /* ---- Collapsible: a labeled line that opens to the detail behind it ---- */
260
- :is(.mkt, .atelic-ui) .collapsible > summary {
261
- display: flex;
262
- align-items: center;
259
+ /* ---- Disclosure, native: a document's fold, a labeled line over its
260
+ summary that opens to the detail behind it. Left uncontrolled, the
261
+ component is a details element wearing .is-native, and these undo the
262
+ card above: no border, no ground, no padding, the body under the line.
263
+ Kept at the card's weight or one class over, so a document's own sheet
264
+ (artifact.css) can size the parts with a rule of the same weight. ---- */
265
+ .atelic-ui .disclosure.is-native {
266
+ border: 0;
267
+ border-radius: 0;
268
+ background: none;
269
+ overflow: visible;
270
+ }
271
+ .atelic-ui .is-native > .disclosure-head {
263
272
  justify-content: space-between;
264
273
  gap: 14px;
274
+ padding: 0;
265
275
  cursor: pointer;
266
276
  list-style: none;
267
277
  }
268
- :is(.mkt, .atelic-ui) .collapsible > summary::-webkit-details-marker {
278
+ .atelic-ui .is-native > .disclosure-head::-webkit-details-marker {
269
279
  display: none;
270
280
  }
271
- :is(.mkt, .atelic-ui) .collapsible-text {
281
+ .atelic-ui .disclosure-text {
272
282
  display: flex;
273
283
  flex-direction: column;
274
284
  gap: 2px;
275
285
  min-width: 0;
276
286
  }
277
- :is(.mkt, .atelic-ui) .collapsible-label {
287
+ .atelic-ui .disclosure-label {
278
288
  font-weight: 650;
279
289
  color: var(--ink);
280
290
  }
281
- :is(.mkt, .atelic-ui) .collapsible-summary {
291
+ .atelic-ui .disclosure-summary {
282
292
  color: var(--ink-soft);
283
293
  text-wrap: pretty;
284
294
  }
285
- :is(.mkt, .atelic-ui) .collapsible > summary:hover .collapsible-label {
295
+ .atelic-ui .is-native > .disclosure-head:hover .disclosure-label {
286
296
  color: var(--ui-primary, var(--primary));
287
297
  }
288
- :is(.mkt, .atelic-ui) .collapsible-chevron {
289
- flex: none;
290
- color: var(--neutral-500);
298
+ .atelic-ui .is-native > .disclosure-head .disclosure-chevron {
291
299
  transition: transform 0.15s;
292
300
  }
293
- :is(.mkt, .atelic-ui) .collapsible[open] > summary .collapsible-chevron {
301
+ .atelic-ui .is-native[open] > .disclosure-head .disclosure-chevron {
294
302
  transform: rotate(180deg);
295
303
  }
296
- :is(.mkt, .atelic-ui) .collapsible-body {
304
+ .atelic-ui .is-native > .disclosure-body {
305
+ border-top: 0;
297
306
  margin-top: 12px;
298
307
  }
299
308
  @media (prefers-reduced-motion: reduce) {
300
- :is(.mkt, .atelic-ui) .collapsible-chevron {
309
+ .atelic-ui .disclosure-chevron,
310
+ .atelic-ui .is-native > .disclosure-head .disclosure-chevron {
301
311
  transition: none;
302
312
  }
303
313
  }
304
- /* Paper cannot be clicked, so a printed collapsible is open. */
314
+ /* Paper cannot be clicked, so a printed native disclosure is open. */
305
315
  @media print {
306
- :is(.mkt, .atelic-ui) .collapsible::details-content {
316
+ .atelic-ui .disclosure.is-native::details-content {
307
317
  content-visibility: visible;
308
318
  display: block;
309
319
  }
310
- :is(.mkt, .atelic-ui) .collapsible-chevron {
320
+ .atelic-ui .is-native > .disclosure-head > .disclosure-chevron {
311
321
  display: none;
312
322
  }
313
323
  }
314
324
 
315
325
  /* ---- Callout: an icon in its tone beside the title, the explainer
316
326
  under it; boxed, it sits apart on a tinted ground ---- */
317
- :is(.mkt, .atelic-ui) .callout {
327
+ .atelic-ui .callout {
318
328
  display: grid;
319
329
  grid-template-columns: auto minmax(0, 1fr);
320
330
  gap: 10px;
321
331
  align-items: start;
322
332
  }
323
- :is(.mkt, .atelic-ui) .callout-icon {
333
+ .atelic-ui .callout-icon {
324
334
  margin-top: 0.15em;
325
335
  color: var(--tone);
326
336
  flex: none;
327
337
  }
328
- :is(.mkt, .atelic-ui) .callout-title {
338
+ .atelic-ui .callout-title {
329
339
  font-weight: 650;
330
340
  color: var(--ink);
331
341
  text-wrap: pretty;
332
342
  }
333
- :is(.mkt, .atelic-ui) .callout-body {
343
+ .atelic-ui .callout-body {
334
344
  margin-top: 2px;
335
345
  color: var(--ink-soft);
336
346
  text-wrap: pretty;
337
347
  }
338
- :is(.mkt, .atelic-ui) .callout.is-box {
348
+ .atelic-ui .callout.is-box {
339
349
  padding: 14px 16px;
340
350
  border-radius: var(--radius-sm);
341
351
  background: var(--tone-bg);
@@ -343,7 +353,7 @@
343
353
  }
344
354
 
345
355
  /* ---- Checklist: checks passed or failed, two columns when there is room ---- */
346
- :is(.mkt, .atelic-ui) .checklist {
356
+ .atelic-ui .checklist {
347
357
  list-style: none;
348
358
  margin: 0;
349
359
  padding: 0;
@@ -352,36 +362,36 @@
352
362
  gap: 12px 28px;
353
363
  }
354
364
  @media print, (min-width: 721px) {
355
- :is(.mkt, .atelic-ui) .checklist {
365
+ .atelic-ui .checklist {
356
366
  grid-template-columns: repeat(2, minmax(0, 1fr));
357
367
  }
358
368
  }
359
- :is(.mkt, .atelic-ui) .checklist li {
369
+ .atelic-ui .checklist li {
360
370
  display: grid;
361
371
  grid-template-columns: auto minmax(0, 1fr);
362
372
  gap: 10px;
363
373
  align-items: start;
364
374
  line-height: 1.4;
365
375
  }
366
- :is(.mkt, .atelic-ui) .checklist li > svg {
376
+ .atelic-ui .checklist li > svg {
367
377
  margin-top: 0.1em;
368
378
  color: var(--tone);
369
379
  }
370
- :is(.mkt, .atelic-ui) .checklist-label {
380
+ .atelic-ui .checklist-label {
371
381
  display: block;
372
382
  font-weight: 600;
373
383
  color: var(--ink);
374
384
  }
375
- :is(.mkt, .atelic-ui) .checklist li[data-tone="bad"] .checklist-label {
385
+ .atelic-ui .checklist li[data-tone="bad"] .checklist-label {
376
386
  color: var(--tone);
377
387
  }
378
- :is(.mkt, .atelic-ui) .checklist-detail {
388
+ .atelic-ui .checklist-detail {
379
389
  display: block;
380
390
  color: var(--ink-soft);
381
391
  }
382
392
 
383
393
  /* ---- The charts' shared key: a swatch, a figure, a label ---- */
384
- :is(.mkt, .atelic-ui) .chart-key {
394
+ .atelic-ui .chart-key {
385
395
  list-style: none;
386
396
  margin: 10px 0 0;
387
397
  padding: 0;
@@ -391,17 +401,17 @@
391
401
  font-size: 0.82rem;
392
402
  color: var(--ink-soft);
393
403
  }
394
- :is(.mkt, .atelic-ui) .chart-key li {
404
+ .atelic-ui .chart-key li {
395
405
  display: inline-flex;
396
406
  align-items: baseline;
397
407
  gap: 7px;
398
408
  }
399
- :is(.mkt, .atelic-ui) .chart-key b {
409
+ .atelic-ui .chart-key b {
400
410
  font-weight: 650;
401
411
  color: var(--ink);
402
412
  font-variant-numeric: tabular-nums;
403
413
  }
404
- :is(.mkt, .atelic-ui) .chart-swatch {
414
+ .atelic-ui .chart-swatch {
405
415
  width: 10px;
406
416
  height: 10px;
407
417
  border-radius: 3px;
@@ -411,35 +421,35 @@
411
421
  }
412
422
 
413
423
  /* ---- StackedBar: one bar, the parts of a whole ---- */
414
- :is(.mkt, .atelic-ui) .stacked-bar-track {
424
+ .atelic-ui .stacked-bar-track {
415
425
  display: flex;
416
426
  gap: 2px;
417
427
  height: 16px;
418
428
  border-radius: 999px;
419
429
  overflow: hidden;
420
430
  }
421
- :is(.mkt, .atelic-ui) .stacked-bar-track span {
431
+ .atelic-ui .stacked-bar-track span {
422
432
  background: var(--tone-fill);
423
433
  min-width: 4px;
424
434
  }
425
435
 
426
436
  /* ---- ColumnChart: a bar a period, the periods in labeled groups ---- */
427
- :is(.mkt, .atelic-ui) .column-chart-plot {
437
+ .atelic-ui .column-chart-plot {
428
438
  display: flex;
429
439
  align-items: flex-end;
430
440
  gap: 12px;
431
441
  min-width: 0;
432
442
  }
433
- :is(.mkt, .atelic-ui) .column-chart-group {
443
+ .atelic-ui .column-chart-group {
434
444
  flex: 1 1 0;
435
445
  min-width: 0;
436
446
  }
437
- :is(.mkt, .atelic-ui) .column-chart-bars {
447
+ .atelic-ui .column-chart-bars {
438
448
  display: flex;
439
449
  align-items: flex-end;
440
450
  gap: 3px;
441
451
  }
442
- :is(.mkt, .atelic-ui) .column-chart-col {
452
+ .atelic-ui .column-chart-col {
443
453
  flex: 1 1 0;
444
454
  min-width: 0;
445
455
  display: flex;
@@ -447,24 +457,24 @@
447
457
  align-items: center;
448
458
  gap: 3px;
449
459
  }
450
- :is(.mkt, .atelic-ui) .column-chart-value {
460
+ .atelic-ui .column-chart-value {
451
461
  font-size: 0.64rem;
452
462
  font-variant-numeric: tabular-nums;
453
463
  color: var(--ink-soft);
454
464
  white-space: nowrap;
455
465
  }
456
- :is(.mkt, .atelic-ui) .column-chart-bar {
466
+ .atelic-ui .column-chart-bar {
457
467
  width: 100%;
458
468
  max-width: 48px;
459
469
  border-radius: 4px 4px 0 0;
460
470
  background: var(--tone-fill);
461
471
  }
462
- :is(.mkt, .atelic-ui) .column-chart-label {
472
+ .atelic-ui .column-chart-label {
463
473
  font-size: 0.66rem;
464
474
  color: var(--ink-soft);
465
475
  white-space: nowrap;
466
476
  }
467
- :is(.mkt, .atelic-ui) .column-chart-group-label {
477
+ .atelic-ui .column-chart-group-label {
468
478
  display: flex;
469
479
  flex-wrap: wrap;
470
480
  justify-content: center;
@@ -478,7 +488,7 @@
478
488
  color: var(--neutral-500);
479
489
  white-space: nowrap;
480
490
  }
481
- :is(.mkt, .atelic-ui) .column-chart-group-label b {
491
+ .atelic-ui .column-chart-group-label b {
482
492
  font-family: var(--font-sans);
483
493
  font-size: 0.8rem;
484
494
  letter-spacing: 0;
@@ -488,37 +498,37 @@
488
498
  }
489
499
 
490
500
  /* ---- ThresholdScale: zones, and a pin a reading ---- */
491
- :is(.mkt, .atelic-ui) .threshold-scale {
501
+ .atelic-ui .threshold-scale {
492
502
  display: flex;
493
503
  flex-direction: column;
494
504
  gap: 10px;
495
505
  }
496
- :is(.mkt, .atelic-ui) .threshold-scale-row {
506
+ .atelic-ui .threshold-scale-row {
497
507
  display: grid;
498
508
  grid-template-columns: 4.4em minmax(0, 1fr) 3.4em;
499
509
  gap: 10px;
500
510
  align-items: center;
501
511
  }
502
- :is(.mkt, .atelic-ui) .threshold-scale-label {
512
+ .atelic-ui .threshold-scale-label {
503
513
  color: var(--ink-soft);
504
514
  }
505
- :is(.mkt, .atelic-ui) .threshold-scale-track {
515
+ .atelic-ui .threshold-scale-track {
506
516
  position: relative;
507
517
  display: flex;
508
518
  gap: 2px;
509
519
  height: 12px;
510
520
  }
511
- :is(.mkt, .atelic-ui) .threshold-scale-zone {
521
+ .atelic-ui .threshold-scale-zone {
512
522
  background: var(--tone-fill);
513
523
  opacity: 0.32;
514
524
  }
515
- :is(.mkt, .atelic-ui) .threshold-scale-zone:first-child {
525
+ .atelic-ui .threshold-scale-zone:first-child {
516
526
  border-radius: 999px 0 0 999px;
517
527
  }
518
- :is(.mkt, .atelic-ui) .threshold-scale-zone:nth-last-child(2) {
528
+ .atelic-ui .threshold-scale-zone:nth-last-child(2) {
519
529
  border-radius: 0 999px 999px 0;
520
530
  }
521
- :is(.mkt, .atelic-ui) .threshold-scale-pin {
531
+ .atelic-ui .threshold-scale-pin {
522
532
  position: absolute;
523
533
  top: 50%;
524
534
  width: 18px;
@@ -529,27 +539,27 @@
529
539
  border: 3px solid var(--ui-card, var(--card));
530
540
  box-shadow: 0 0 0 1.5px var(--tone-fill);
531
541
  }
532
- :is(.mkt, .atelic-ui) .threshold-scale-value {
542
+ .atelic-ui .threshold-scale-value {
533
543
  font-weight: 700;
534
544
  font-variant-numeric: tabular-nums;
535
545
  color: var(--tone);
536
546
  text-align: right;
537
547
  }
538
- :is(.mkt, .atelic-ui) .threshold-scale-axis {
548
+ .atelic-ui .threshold-scale-axis {
539
549
  position: relative;
540
550
  display: flex;
541
551
  gap: 2px;
542
552
  height: 2.3em;
543
553
  font-size: 0.8rem;
544
554
  }
545
- :is(.mkt, .atelic-ui) .threshold-scale-axis > span {
555
+ .atelic-ui .threshold-scale-axis > span {
546
556
  color: var(--tone);
547
557
  font-weight: 600;
548
558
  white-space: nowrap;
549
559
  overflow: hidden;
550
560
  text-overflow: ellipsis;
551
561
  }
552
- :is(.mkt, .atelic-ui) .threshold-scale-axis > i {
562
+ .atelic-ui .threshold-scale-axis > i {
553
563
  position: absolute;
554
564
  top: 1.25em;
555
565
  transform: translateX(-50%);
@@ -563,12 +573,12 @@
563
573
  /* ---- DataTable: on a phone each row stacks, its facts wearing their
564
574
  column's label, and a dropdown sorts; wide, it is a table whose
565
575
  headings sort ---- */
566
- :is(.mkt, .atelic-ui) .data-table table,
567
- :is(.mkt, .atelic-ui) .data-table tbody {
576
+ .atelic-ui .data-table table,
577
+ .atelic-ui .data-table tbody {
568
578
  display: block;
569
579
  width: 100%;
570
580
  }
571
- :is(.mkt, .atelic-ui) .data-table thead {
581
+ .atelic-ui .data-table thead {
572
582
  position: absolute;
573
583
  width: 1px;
574
584
  height: 1px;
@@ -576,7 +586,7 @@
576
586
  clip: rect(0, 0, 0, 0);
577
587
  white-space: nowrap;
578
588
  }
579
- :is(.mkt, .atelic-ui) .data-table-sort {
589
+ .atelic-ui .data-table-sort {
580
590
  display: flex;
581
591
  align-items: center;
582
592
  gap: 8px;
@@ -584,7 +594,7 @@
584
594
  font-size: 0.85rem;
585
595
  color: var(--ink-soft);
586
596
  }
587
- :is(.mkt, .atelic-ui) .data-table-sort select {
597
+ .atelic-ui .data-table-sort select {
588
598
  font: inherit;
589
599
  color: var(--ink);
590
600
  background: var(--ui-card, var(--card));
@@ -593,7 +603,7 @@
593
603
  padding: 5px 8px;
594
604
  max-width: 100%;
595
605
  }
596
- :is(.mkt, .atelic-ui) .data-table tbody tr {
606
+ .atelic-ui .data-table tbody tr {
597
607
  display: flex;
598
608
  flex-wrap: wrap;
599
609
  align-items: center;
@@ -602,25 +612,25 @@
602
612
  border-bottom: 1px solid var(--neutral-100);
603
613
  line-height: 1.35;
604
614
  }
605
- :is(.mkt, .atelic-ui) .data-table tbody tr:first-child {
615
+ .atelic-ui .data-table tbody tr:first-child {
606
616
  border-top: 1.5px solid var(--ink);
607
617
  }
608
- :is(.mkt, .atelic-ui) .data-table tbody tr:last-child {
618
+ .atelic-ui .data-table tbody tr:last-child {
609
619
  border-bottom: 0;
610
620
  padding-bottom: 0;
611
621
  }
612
- :is(.mkt, .atelic-ui) .data-table tbody th {
622
+ .atelic-ui .data-table tbody th {
613
623
  width: 100%;
614
624
  text-align: left;
615
625
  font-weight: 400;
616
626
  }
617
- :is(.mkt, .atelic-ui) .data-table td {
627
+ .atelic-ui .data-table td {
618
628
  display: inline-flex;
619
629
  align-items: center;
620
630
  gap: 6px;
621
631
  font-variant-numeric: tabular-nums;
622
632
  }
623
- :is(.mkt, .atelic-ui) .data-table td::before {
633
+ .atelic-ui .data-table td::before {
624
634
  content: attr(data-label);
625
635
  font-family: var(--font-mono);
626
636
  font-size: 0.7rem;
@@ -629,33 +639,33 @@
629
639
  color: var(--neutral-500);
630
640
  }
631
641
  @media print, (min-width: 721px) {
632
- :is(.mkt, .atelic-ui) .data-table-sort {
642
+ .atelic-ui .data-table-sort {
633
643
  display: none;
634
644
  }
635
- :is(.mkt, .atelic-ui) .data-table table {
645
+ .atelic-ui .data-table table {
636
646
  display: table;
637
647
  border-collapse: collapse;
638
648
  }
639
- :is(.mkt, .atelic-ui) .data-table tbody {
649
+ .atelic-ui .data-table tbody {
640
650
  display: table-row-group;
641
651
  }
642
- :is(.mkt, .atelic-ui) .data-table thead {
652
+ .atelic-ui .data-table thead {
643
653
  position: static;
644
654
  width: auto;
645
655
  height: auto;
646
656
  overflow: visible;
647
657
  clip: auto;
648
658
  }
649
- :is(.mkt, .atelic-ui) .data-table tbody tr {
659
+ .atelic-ui .data-table tbody tr {
650
660
  display: table-row;
651
661
  padding: 0;
652
662
  border: 0;
653
663
  }
654
- :is(.mkt, .atelic-ui) .data-table tbody tr:first-child {
664
+ .atelic-ui .data-table tbody tr:first-child {
655
665
  border-top: 0;
656
666
  }
657
- :is(.mkt, .atelic-ui) .data-table th,
658
- :is(.mkt, .atelic-ui) .data-table td {
667
+ .atelic-ui .data-table th,
668
+ .atelic-ui .data-table td {
659
669
  display: table-cell;
660
670
  padding: 7px 14px 7px 0;
661
671
  border-bottom: 1px solid var(--neutral-100);
@@ -663,23 +673,23 @@
663
673
  vertical-align: middle;
664
674
  font-weight: 400;
665
675
  }
666
- :is(.mkt, .atelic-ui) .data-table tbody th {
676
+ .atelic-ui .data-table tbody th {
667
677
  width: auto;
668
678
  }
669
- :is(.mkt, .atelic-ui) .data-table td::before {
679
+ .atelic-ui .data-table td::before {
670
680
  content: none;
671
681
  }
672
- :is(.mkt, .atelic-ui) .data-table th:last-child,
673
- :is(.mkt, .atelic-ui) .data-table td:last-child {
682
+ .atelic-ui .data-table th:last-child,
683
+ .atelic-ui .data-table td:last-child {
674
684
  padding-right: 0;
675
685
  }
676
- :is(.mkt, .atelic-ui) .data-table [data-align="center"] {
686
+ .atelic-ui .data-table [data-align="center"] {
677
687
  text-align: center;
678
688
  }
679
- :is(.mkt, .atelic-ui) .data-table [data-align="right"] {
689
+ .atelic-ui .data-table [data-align="right"] {
680
690
  text-align: right;
681
691
  }
682
- :is(.mkt, .atelic-ui) .data-table thead th {
692
+ .atelic-ui .data-table thead th {
683
693
  padding-top: 0;
684
694
  padding-bottom: 8px;
685
695
  border-bottom: 1.5px solid var(--ink);
@@ -691,7 +701,7 @@
691
701
  white-space: nowrap;
692
702
  vertical-align: bottom;
693
703
  }
694
- :is(.mkt, .atelic-ui) .data-table thead th button {
704
+ .atelic-ui .data-table thead th button {
695
705
  display: inline-flex;
696
706
  align-items: center;
697
707
  gap: 4px;
@@ -704,23 +714,23 @@
704
714
  color: inherit;
705
715
  cursor: pointer;
706
716
  }
707
- :is(.mkt, .atelic-ui) .data-table thead th button:hover,
708
- :is(.mkt, .atelic-ui) .data-table thead th button[data-active] {
717
+ .atelic-ui .data-table thead th button:hover,
718
+ .atelic-ui .data-table thead th button[data-active] {
709
719
  color: var(--ui-primary, var(--primary));
710
720
  }
711
- :is(.mkt, .atelic-ui) .data-table thead th button svg {
721
+ .atelic-ui .data-table thead th button svg {
712
722
  opacity: 0.55;
713
723
  }
714
- :is(.mkt, .atelic-ui) .data-table thead th button[data-active] svg {
724
+ .atelic-ui .data-table thead th button[data-active] svg {
715
725
  opacity: 1;
716
726
  }
717
- :is(.mkt, .atelic-ui) .data-table tbody tr:last-child th,
718
- :is(.mkt, .atelic-ui) .data-table tbody tr:last-child td {
727
+ .atelic-ui .data-table tbody tr:last-child th,
728
+ .atelic-ui .data-table tbody tr:last-child td {
719
729
  border-bottom: 0;
720
730
  }
721
731
  }
722
732
  @media print {
723
- :is(.mkt, .atelic-ui) .data-table thead th button svg {
733
+ .atelic-ui .data-table thead th button svg {
724
734
  display: none;
725
735
  }
726
736
  }