create-feedbax 0.1.0 → 0.2.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 (210) hide show
  1. package/LICENSE +201 -21
  2. package/README.md +11 -1
  3. package/dist/cli.js +1261 -26
  4. package/dist/index.js +1402 -160
  5. package/package.json +40 -14
  6. package/template/.feedbax-template.sha256 +1 -0
  7. package/template/.gitignore.template +6 -0
  8. package/template/.npmignore.template +5 -0
  9. package/template/.prettierignore.template +4 -0
  10. package/template/LICENSE +201 -0
  11. package/template/components.json +25 -0
  12. package/template/eslint.config.mjs +25 -0
  13. package/template/package.json +70 -14
  14. package/template/public/feedbax-mark.svg +4 -0
  15. package/template/public/robots.txt +3 -0
  16. package/template/src/authorized-draft-post.test.tsx +212 -0
  17. package/template/src/authorized-draft-post.tsx +204 -0
  18. package/template/src/authorized-draft-query.ts +74 -0
  19. package/template/src/browser-post-state.test.ts +120 -0
  20. package/template/src/browser-post-state.ts +134 -0
  21. package/template/src/browser-vote-state.test.ts +14 -0
  22. package/template/src/browser-vote-state.ts +27 -0
  23. package/template/src/capability-authorization-error.ts +3 -0
  24. package/template/src/changelog-page.test.tsx +139 -0
  25. package/template/src/changelog-page.tsx +219 -0
  26. package/template/src/changelog-query.ts +13 -0
  27. package/template/src/changelog-runtime.ts +27 -0
  28. package/template/src/cloudflare-turnstile.ts +31 -0
  29. package/template/src/cloudflare-workers-test.ts +3 -0
  30. package/template/src/cloudflare-workers.d.ts +18 -0
  31. package/template/src/comment-creation.test.tsx +270 -0
  32. package/template/src/comment-profile.ts +5 -0
  33. package/template/src/comment-thread-page.ts +18 -0
  34. package/template/src/components/command-palette-context.tsx +71 -0
  35. package/template/src/components/command-palette.tsx +246 -0
  36. package/template/src/components/create-post-trigger.tsx +44 -0
  37. package/template/src/components/device-profile-provider.tsx +309 -0
  38. package/template/src/components/header.tsx +95 -0
  39. package/template/src/components/loader.tsx +10 -0
  40. package/template/src/components/profile-menu.tsx +89 -0
  41. package/template/src/components/ui/components/alert-dialog.tsx +185 -0
  42. package/template/src/components/ui/components/attachment.tsx +207 -0
  43. package/template/src/components/ui/components/avatar.tsx +107 -0
  44. package/template/src/components/ui/components/badge.tsx +52 -0
  45. package/template/src/components/ui/components/bubble.tsx +128 -0
  46. package/template/src/components/ui/components/button-group.tsx +87 -0
  47. package/template/src/components/ui/components/button.tsx +56 -0
  48. package/template/src/components/ui/components/card.tsx +103 -0
  49. package/template/src/components/ui/components/checkbox.tsx +26 -0
  50. package/template/src/components/ui/components/command.tsx +194 -0
  51. package/template/src/components/ui/components/dialog.tsx +154 -0
  52. package/template/src/components/ui/components/drawer.tsx +229 -0
  53. package/template/src/components/ui/components/dropdown-menu.tsx +270 -0
  54. package/template/src/components/ui/components/empty.tsx +101 -0
  55. package/template/src/components/ui/components/field.tsx +236 -0
  56. package/template/src/components/ui/components/input-group.tsx +155 -0
  57. package/template/src/components/ui/components/input.tsx +20 -0
  58. package/template/src/components/ui/components/item.tsx +201 -0
  59. package/template/src/components/ui/components/kbd.tsx +26 -0
  60. package/template/src/components/ui/components/label.tsx +18 -0
  61. package/template/src/components/ui/components/marker.tsx +71 -0
  62. package/template/src/components/ui/components/message-scroller.tsx +128 -0
  63. package/template/src/components/ui/components/message.tsx +92 -0
  64. package/template/src/components/ui/components/native-select.tsx +65 -0
  65. package/template/src/components/ui/components/popover.tsx +88 -0
  66. package/template/src/components/ui/components/portal-primitives.test.tsx +85 -0
  67. package/template/src/components/ui/components/radio-group.tsx +36 -0
  68. package/template/src/components/ui/components/scroll-area.tsx +52 -0
  69. package/template/src/components/ui/components/secondary-form-actions.test.tsx +23 -0
  70. package/template/src/components/ui/components/select.tsx +199 -0
  71. package/template/src/components/ui/components/separator.tsx +23 -0
  72. package/template/src/components/ui/components/sheet.tsx +135 -0
  73. package/template/src/components/ui/components/skeleton.tsx +13 -0
  74. package/template/src/components/ui/components/sonner.tsx +43 -0
  75. package/template/src/components/ui/components/spinner.tsx +16 -0
  76. package/template/src/components/ui/components/tabs.tsx +80 -0
  77. package/template/src/components/ui/components/textarea.tsx +18 -0
  78. package/template/src/components/ui/components/tooltip.tsx +64 -0
  79. package/template/src/components/ui/hooks/.gitkeep +0 -0
  80. package/template/src/components/ui/lib/utils.ts +6 -0
  81. package/template/src/components/ui/styles/globals.css +151 -0
  82. package/template/src/create-post-overlay.tsx +82 -0
  83. package/template/src/draft-post-list.tsx +39 -0
  84. package/template/src/feedback-cache-invalidation.test.ts +185 -0
  85. package/template/src/feedback-cache-invalidation.ts +97 -0
  86. package/template/src/feedback-runtime.ts +38 -0
  87. package/template/src/feedbax/changelog/index.test.ts +156 -0
  88. package/template/src/feedbax/changelog/index.ts +206 -0
  89. package/template/src/feedbax/changelog/notion-changelog.test.ts +395 -0
  90. package/template/src/feedbax/changelog/notion-changelog.ts +400 -0
  91. package/template/src/feedbax/config/index.test.ts +111 -0
  92. package/template/src/feedbax/config/index.ts +271 -0
  93. package/template/src/feedbax/feedback/feedback-storage.ts +43 -0
  94. package/template/src/feedbax/feedback/index.test.ts +900 -0
  95. package/template/src/feedbax/feedback/index.ts +942 -0
  96. package/template/src/feedbax/feedback/notion-comments.test.ts +171 -0
  97. package/template/src/feedbax/feedback/notion-comments.ts +231 -0
  98. package/template/src/feedbax/feedback/notion-data-source.test.ts +364 -0
  99. package/template/src/feedbax/feedback/notion-data-source.ts +458 -0
  100. package/template/src/feedbax/feedback/notion-feedback.test.ts +998 -0
  101. package/template/src/feedbax/feedback/notion-feedback.ts +651 -0
  102. package/template/src/feedbax/feedback/notion-request.ts +74 -0
  103. package/template/src/feedbax.test-fixture.ts +64 -0
  104. package/template/src/feedbax.ts +69 -0
  105. package/template/src/index.css +2138 -0
  106. package/template/src/lazy-create-post-overlay.tsx +6 -0
  107. package/template/src/lazy-post-detail-overlay.tsx +10 -0
  108. package/template/src/masked-post-link.tsx +27 -0
  109. package/template/src/overlay-post-detail.test.tsx +130 -0
  110. package/template/src/overlay-post-detail.tsx +92 -0
  111. package/template/src/portal-comments.test.ts +375 -0
  112. package/template/src/portal-comments.ts +384 -0
  113. package/template/src/portal-features.test.tsx +150 -0
  114. package/template/src/portal-feedback-form.tsx +515 -0
  115. package/template/src/portal-feedback-runtime.test.ts +32 -0
  116. package/template/src/portal-feedback-runtime.ts +55 -0
  117. package/template/src/portal-feedback-server-function.ts +93 -0
  118. package/template/src/portal-feedback-submission.test.ts +307 -0
  119. package/template/src/portal-feedback-submission.ts +214 -0
  120. package/template/src/portal-head.ts +58 -0
  121. package/template/src/portal-server-entry.ts +64 -0
  122. package/template/src/portal-voting.test.ts +106 -0
  123. package/template/src/portal-voting.ts +149 -0
  124. package/template/src/post-badges.tsx +27 -0
  125. package/template/src/post-creation-flow.test.tsx +230 -0
  126. package/template/src/post-creation-flow.tsx +88 -0
  127. package/template/src/post-detail-overlay.test.tsx +114 -0
  128. package/template/src/post-detail-overlay.tsx +67 -0
  129. package/template/src/post-feed-controls.test.tsx +239 -0
  130. package/template/src/post-feed-controls.tsx +298 -0
  131. package/template/src/post-presentation.ts +37 -0
  132. package/template/src/post-queries.test.ts +158 -0
  133. package/template/src/post-queries.ts +26 -0
  134. package/template/src/post-results.tsx +165 -0
  135. package/template/src/public-cache-policy.test.ts +141 -0
  136. package/template/src/public-cache-policy.ts +119 -0
  137. package/template/src/public-cache-tags.ts +7 -0
  138. package/template/src/public-changelog-page.ts +15 -0
  139. package/template/src/public-changelog-server-function.ts +27 -0
  140. package/template/src/public-date.ts +11 -0
  141. package/template/src/public-failure-state.test.tsx +69 -0
  142. package/template/src/public-feedback-index.tsx +124 -0
  143. package/template/src/public-feedback-page.test.tsx +290 -0
  144. package/template/src/public-feedback-page.ts +75 -0
  145. package/template/src/public-feedback-server-function.ts +22 -0
  146. package/template/src/public-portal-error.tsx +27 -0
  147. package/template/src/public-post-detail.tsx +682 -0
  148. package/template/src/public-post-page.test.tsx +173 -0
  149. package/template/src/public-post-page.ts +15 -0
  150. package/template/src/public-post-route.test.tsx +214 -0
  151. package/template/src/public-post-route.tsx +171 -0
  152. package/template/src/public-post-server-function.ts +48 -0
  153. package/template/src/public-post-unavailable.tsx +10 -0
  154. package/template/src/public-roadmap-page.test.tsx +139 -0
  155. package/template/src/public-roadmap-page.ts +24 -0
  156. package/template/src/public-roadmap-route.test.tsx +218 -0
  157. package/template/src/public-roadmap-route.tsx +50 -0
  158. package/template/src/public-roadmap-server-function.ts +44 -0
  159. package/template/src/public-roadmap-view.tsx +378 -0
  160. package/template/src/public-shell.test.tsx +518 -0
  161. package/template/src/roadmap-query.ts +21 -0
  162. package/template/src/root-branding.test.ts +53 -0
  163. package/template/src/routeTree.gen.ts +131 -0
  164. package/template/src/routed-post-creation-form.tsx +28 -0
  165. package/template/src/router.tsx +25 -0
  166. package/template/src/routes/__root.tsx +116 -0
  167. package/template/src/routes/changelog.tsx +39 -0
  168. package/template/src/routes/index.tsx +61 -0
  169. package/template/src/routes/p.$slug.tsx +16 -0
  170. package/template/src/routes/roadmap.tsx +11 -0
  171. package/template/src/routes/submit.tsx +28 -0
  172. package/template/src/safe-public-failure.ts +45 -0
  173. package/template/src/server.ts +111 -0
  174. package/template/src/similar-posts.tsx +45 -0
  175. package/template/src/submit-route.test.tsx +134 -0
  176. package/template/src/trusted-feedback-handler.test.ts +425 -0
  177. package/template/src/trusted-feedback-handler.ts +181 -0
  178. package/template/src/trusted-feedback-runtime.ts +17 -0
  179. package/template/src/turnstile-configuration.test.ts +37 -0
  180. package/template/src/turnstile-configuration.ts +19 -0
  181. package/template/src/use-media-query.ts +17 -0
  182. package/template/src/vote-toggle.test.tsx +171 -0
  183. package/template/src/vote-toggle.tsx +211 -0
  184. package/template/tsconfig.json +45 -0
  185. package/template/vite.config.ts +20 -0
  186. package/template/vitest.config.ts +4 -0
  187. package/template/vitest.setup.ts +3 -0
  188. package/template/wrangler.jsonc +35 -0
  189. package/dist/cli.d.ts +0 -3
  190. package/dist/cli.d.ts.map +0 -1
  191. package/dist/cli.js.map +0 -1
  192. package/dist/index.d.ts +0 -21
  193. package/dist/index.d.ts.map +0 -1
  194. package/dist/index.js.map +0 -1
  195. package/template/.env.example +0 -4
  196. package/template/README.md +0 -7
  197. package/template/apps/portal/components.json +0 -20
  198. package/template/apps/portal/package.json +0 -31
  199. package/template/apps/portal/src/lib/utils.ts +0 -6
  200. package/template/apps/portal/src/routeTree.gen.ts +0 -59
  201. package/template/apps/portal/src/router.tsx +0 -10
  202. package/template/apps/portal/src/routes/__root.tsx +0 -31
  203. package/template/apps/portal/src/routes/index.tsx +0 -35
  204. package/template/apps/portal/src/styles.css +0 -91
  205. package/template/apps/portal/tsconfig.json +0 -15
  206. package/template/apps/portal/vite.config.ts +0 -13
  207. package/template/feedbax.config.ts +0 -13
  208. package/template/feedbax.jsonc +0 -11
  209. package/template/pnpm-workspace.yaml +0 -3
  210. package/template/turbo.json +0 -8
@@ -0,0 +1,2138 @@
1
+ @import "@feedbax/ui/globals.css";
2
+
3
+ :root {
4
+ --portal-ink: var(--foreground);
5
+ --portal-paper: var(--background);
6
+ --portal-accent: var(--primary);
7
+ --portal-rule: var(--border);
8
+ }
9
+ .sr-only {
10
+ position: absolute;
11
+ width: 1px;
12
+ height: 1px;
13
+ padding: 0;
14
+ margin: -1px;
15
+ overflow: hidden;
16
+ clip: rect(0, 0, 0, 0);
17
+ white-space: nowrap;
18
+ border: 0;
19
+ }
20
+ .post-controls {
21
+ display: flex;
22
+ align-items: end;
23
+ gap: 0.75rem;
24
+ margin: 2.5rem 0 0;
25
+ padding-block: 1rem;
26
+ border-block: 1px solid var(--portal-rule);
27
+ }
28
+ .post-controls label {
29
+ display: grid;
30
+ gap: 0.35rem;
31
+ font-size: 0.75rem;
32
+ }
33
+ .post-search {
34
+ position: relative;
35
+ flex: 1;
36
+ }
37
+ .post-search svg {
38
+ position: absolute;
39
+ left: 0.75rem;
40
+ bottom: 0.75rem;
41
+ width: 1rem;
42
+ }
43
+ .post-search input {
44
+ width: 100%;
45
+ min-height: 2.75rem;
46
+ padding-left: 2.25rem;
47
+ }
48
+ .post-controls select,
49
+ .post-controls button,
50
+ .post-filters summary {
51
+ min-height: 2.75rem;
52
+ padding: 0.65rem 0.85rem;
53
+ border: 1px solid var(--portal-rule);
54
+ background: var(--portal-paper);
55
+ color: var(--portal-ink);
56
+ }
57
+ .post-filters {
58
+ position: relative;
59
+ }
60
+ .post-filters > div,
61
+ .post-filters fieldset {
62
+ display: flex;
63
+ gap: 0.65rem;
64
+ }
65
+ .post-filters[open] {
66
+ padding: 1rem;
67
+ border: 1px solid var(--portal-rule);
68
+ }
69
+ .profile-control {
70
+ position: relative;
71
+ }
72
+ .profile-control summary {
73
+ cursor: pointer;
74
+ }
75
+ .profile-panel {
76
+ position: absolute;
77
+ z-index: 20;
78
+ right: 0;
79
+ width: min(22rem, 85vw);
80
+ padding: 1rem;
81
+ border: 1px solid var(--portal-rule);
82
+ background: var(--portal-paper);
83
+ }
84
+ .profile-panel form,
85
+ .profile-panel label {
86
+ display: grid;
87
+ gap: 0.5rem;
88
+ }
89
+ .roadmap-groups {
90
+ overflow-x: auto;
91
+ scroll-snap-type: x mandatory;
92
+ }
93
+ .roadmap-group {
94
+ scroll-snap-align: start;
95
+ }
96
+ .draft-post-link {
97
+ border-style: dashed;
98
+ background: color-mix(in srgb, var(--portal-ink) 5%, var(--portal-paper));
99
+ }
100
+ .draft-post-link strong {
101
+ border: 1px solid currentColor;
102
+ padding: 0.15rem 0.4rem;
103
+ font-size: 0.68rem;
104
+ text-transform: uppercase;
105
+ }
106
+ @media (max-width: 720px) {
107
+ .portal-header nav {
108
+ gap: 0.65rem;
109
+ overflow-x: auto;
110
+ }
111
+ .portal-header nav a {
112
+ font-size: 0.65rem;
113
+ }
114
+ .post-controls {
115
+ align-items: stretch;
116
+ flex-direction: column;
117
+ }
118
+ .post-filters fieldset {
119
+ flex-direction: column;
120
+ }
121
+ }
122
+ @media (prefers-reduced-motion: reduce) {
123
+ *,
124
+ *::before,
125
+ *::after {
126
+ scroll-behavior: auto !important;
127
+ animation-duration: 0.01ms !important;
128
+ animation-iteration-count: 1 !important;
129
+ transition-duration: 0.01ms !important;
130
+ }
131
+ }
132
+ .mobile-menu {
133
+ display: none;
134
+ border: 0;
135
+ background: transparent;
136
+ color: inherit;
137
+ }
138
+ .portal-header .mobile-nav {
139
+ display: grid;
140
+ align-items: stretch;
141
+ gap: 1rem;
142
+ overflow: visible;
143
+ padding: 1.5rem;
144
+ }
145
+ @media (max-width: 720px) {
146
+ .portal-header .desktop-nav {
147
+ display: none;
148
+ }
149
+ .mobile-menu {
150
+ display: inline-grid;
151
+ place-items: center;
152
+ }
153
+ }
154
+
155
+ body {
156
+ margin: 0;
157
+ background:
158
+ linear-gradient(
159
+ color-mix(in srgb, var(--foreground) 3.5%, transparent) 1px,
160
+ transparent 1px
161
+ ),
162
+ var(--portal-paper);
163
+ background-size: 100% 4rem;
164
+ color: var(--portal-ink);
165
+ }
166
+
167
+ a,
168
+ button,
169
+ select,
170
+ input,
171
+ textarea {
172
+ -webkit-tap-highlight-color: transparent;
173
+ }
174
+
175
+ a:focus-visible,
176
+ button:focus-visible,
177
+ select:focus-visible,
178
+ input:focus-visible,
179
+ textarea:focus-visible {
180
+ outline: 3px solid color-mix(in srgb, var(--portal-accent) 65%, transparent);
181
+ outline-offset: 3px;
182
+ }
183
+
184
+ .vote-toggle-button {
185
+ display: inline-flex;
186
+ min-height: 2.5rem;
187
+ align-items: center;
188
+ justify-content: center;
189
+ gap: 0.35rem;
190
+ padding: 0.5rem 0.75rem;
191
+ border: 1px solid var(--portal-rule);
192
+ background: var(--card);
193
+ color: var(--portal-ink);
194
+ font: inherit;
195
+ font-weight: 650;
196
+ cursor: pointer;
197
+ transition:
198
+ border-color 160ms ease,
199
+ background-color 160ms ease,
200
+ color 160ms ease,
201
+ transform 160ms ease;
202
+ }
203
+
204
+ .vote-toggle-button:hover:not(:disabled),
205
+ .vote-toggle-button:focus-visible {
206
+ border-color: color-mix(
207
+ in srgb,
208
+ var(--portal-accent) 55%,
209
+ var(--portal-rule)
210
+ );
211
+ background: color-mix(in srgb, var(--portal-accent) 10%, var(--card));
212
+ color: var(--portal-accent);
213
+ transform: translateY(-1px);
214
+ }
215
+
216
+ .vote-toggle-button[aria-pressed="true"] {
217
+ border-color: color-mix(
218
+ in srgb,
219
+ var(--portal-accent) 50%,
220
+ var(--portal-rule)
221
+ );
222
+ background: color-mix(in srgb, var(--portal-accent) 14%, var(--card));
223
+ color: var(--portal-accent);
224
+ }
225
+
226
+ .vote-toggle-button:disabled {
227
+ cursor: wait;
228
+ opacity: 0.65;
229
+ }
230
+
231
+ .vote-toggle-button svg {
232
+ width: 1rem;
233
+ height: 1rem;
234
+ stroke-width: 2.5;
235
+ }
236
+
237
+ .feedback-submit {
238
+ display: grid;
239
+ grid-template-columns: minmax(0, 0.8fr) minmax(20rem, 1.2fr);
240
+ gap: clamp(2rem, 7vw, 7rem);
241
+ margin-top: clamp(3.5rem, 8vw, 7rem);
242
+ padding: clamp(2rem, 5vw, 4rem);
243
+ border: 1px solid var(--portal-rule);
244
+ background: var(--card);
245
+ }
246
+
247
+ .create-post-dialog {
248
+ max-height: min(90dvh, 52rem);
249
+ width: min(62rem, calc(100vw - 2rem));
250
+ max-width: min(62rem, calc(100vw - 2rem));
251
+ overflow-y: auto;
252
+ padding: 0;
253
+ }
254
+
255
+ .create-post-drawer {
256
+ max-height: calc(100svh - 1rem);
257
+ }
258
+
259
+ .create-post-drawer .feedback-submit {
260
+ overflow-y: auto;
261
+ overscroll-behavior: contain;
262
+ }
263
+
264
+ .feedback-submit[data-display="overlay"] {
265
+ grid-template-columns: minmax(0, 0.7fr) minmax(20rem, 1.3fr);
266
+ gap: 2rem;
267
+ margin: 0;
268
+ padding: clamp(1.5rem, 4vw, 3rem);
269
+ border: 0;
270
+ background: transparent;
271
+ }
272
+
273
+ .feedback-submit-copy h2 {
274
+ margin: 0;
275
+ font-size: clamp(2rem, 4vw, 3.8rem);
276
+ font-weight: 650;
277
+ letter-spacing: -0.06em;
278
+ line-height: 0.98;
279
+ }
280
+
281
+ .feedback-submit-copy > p:last-child {
282
+ margin: 1.5rem 0 0;
283
+ color: var(--muted-foreground);
284
+ font-size: 0.88rem;
285
+ line-height: 1.65;
286
+ }
287
+
288
+ .feedback-submit-form,
289
+ .feedback-submit-field {
290
+ display: grid;
291
+ }
292
+
293
+ .feedback-submit-form {
294
+ gap: 1rem;
295
+ }
296
+
297
+ .feedback-submit-field {
298
+ gap: 0.5rem;
299
+ }
300
+
301
+ .feedback-submit-field > label {
302
+ color: var(--muted-foreground);
303
+ font-size: 0.68rem;
304
+ font-weight: 750;
305
+ letter-spacing: 0.08em;
306
+ text-transform: uppercase;
307
+ }
308
+
309
+ .feedback-character-count,
310
+ .feedback-field-error {
311
+ font-size: 0.72rem;
312
+ }
313
+
314
+ .feedback-character-count {
315
+ color: var(--muted-foreground);
316
+ text-align: right;
317
+ }
318
+
319
+ .feedback-field-error {
320
+ color: var(--destructive);
321
+ }
322
+
323
+ .feedback-submit-form input,
324
+ .feedback-submit-form textarea,
325
+ .feedback-submit-form select {
326
+ box-sizing: border-box;
327
+ width: 100%;
328
+ border: 1px solid var(--input);
329
+ border-radius: 0;
330
+ background: var(--portal-paper);
331
+ color: var(--portal-ink);
332
+ font: inherit;
333
+ }
334
+
335
+ .feedback-submit-form input,
336
+ .feedback-submit-form select {
337
+ min-height: 3rem;
338
+ padding: 0 0.85rem;
339
+ }
340
+
341
+ .feedback-submit-form textarea {
342
+ min-height: 9rem;
343
+ padding: 0.85rem;
344
+ resize: vertical;
345
+ }
346
+
347
+ .feedback-post-type-picker {
348
+ grid-template-columns: repeat(3, minmax(0, 1fr));
349
+ gap: 0.625rem;
350
+ }
351
+
352
+ .feedback-post-type-card {
353
+ position: relative;
354
+ display: grid;
355
+ box-sizing: border-box;
356
+ width: 100%;
357
+ min-height: 8rem;
358
+ grid-template-columns: 1fr auto;
359
+ grid-template-rows: auto 1fr;
360
+ gap: 1.25rem 0.75rem;
361
+ align-content: space-between;
362
+ padding: 1rem;
363
+ border: 1px solid var(--portal-rule);
364
+ background: var(--background);
365
+ color: var(--foreground);
366
+ cursor: pointer;
367
+ text-transform: none;
368
+ transition:
369
+ border-color 160ms ease,
370
+ background-color 160ms ease,
371
+ transform 160ms ease;
372
+ }
373
+
374
+ .feedback-post-type-card:hover {
375
+ border-color: color-mix(
376
+ in srgb,
377
+ var(--portal-accent) 55%,
378
+ var(--portal-rule)
379
+ );
380
+ background: color-mix(in srgb, var(--portal-accent) 5%, var(--background));
381
+ transform: translateY(-2px);
382
+ }
383
+
384
+ .feedback-post-type-card:has([data-checked]) {
385
+ border-color: var(--portal-accent);
386
+ background: color-mix(in srgb, var(--portal-accent) 10%, var(--background));
387
+ }
388
+
389
+ .feedback-post-type-card:has(:focus-visible) {
390
+ border-color: var(--ring);
391
+ outline: 2px solid color-mix(in srgb, var(--ring) 55%, transparent);
392
+ outline-offset: 2px;
393
+ }
394
+
395
+ .feedback-post-type-card > [data-slot="radio-group-item"] {
396
+ grid-column: 2;
397
+ grid-row: 1;
398
+ }
399
+
400
+ .feedback-post-type-card > svg {
401
+ width: 1.35rem;
402
+ height: 1.35rem;
403
+ grid-column: 1;
404
+ grid-row: 1;
405
+ color: var(--portal-accent);
406
+ stroke-width: 1.75;
407
+ }
408
+
409
+ .feedback-post-type-copy {
410
+ display: grid;
411
+ grid-column: 1 / -1;
412
+ grid-row: 2;
413
+ gap: 0.3rem;
414
+ align-self: end;
415
+ }
416
+
417
+ .feedback-post-type-copy strong {
418
+ font-size: 0.78rem;
419
+ line-height: 1.25;
420
+ }
421
+
422
+ .feedback-post-type-copy small {
423
+ color: var(--muted-foreground);
424
+ font-size: 0.68rem;
425
+ font-weight: 500;
426
+ line-height: 1.4;
427
+ }
428
+
429
+ .feedback-submit-actions {
430
+ display: flex;
431
+ flex-wrap: wrap;
432
+ gap: 0.75rem;
433
+ }
434
+
435
+ .feedback-submit-actions button {
436
+ min-height: 3rem;
437
+ padding: 0 1.25rem;
438
+ border-radius: 0;
439
+ cursor: pointer;
440
+ font: inherit;
441
+ font-size: 0.82rem;
442
+ font-weight: 750;
443
+ }
444
+
445
+ .feedback-submit-actions button:disabled {
446
+ cursor: wait;
447
+ opacity: 0.6;
448
+ }
449
+
450
+ .feedback-submit-actions .feedback-withdraw {
451
+ background: transparent;
452
+ color: var(--destructive);
453
+ }
454
+
455
+ .feedback-submit-actions .feedback-cancel {
456
+ background: transparent;
457
+ color: var(--portal-ink);
458
+ }
459
+
460
+ .feedback-submit-message {
461
+ margin: 0;
462
+ color: var(--portal-accent);
463
+ font-size: 0.85rem;
464
+ font-weight: 650;
465
+ }
466
+
467
+ .post-detail-dialog {
468
+ display: block;
469
+ width: min(70rem, calc(100vw - 2rem));
470
+ max-width: 70rem;
471
+ max-height: calc(100svh - 2rem);
472
+ overflow-y: auto;
473
+ padding: 0;
474
+ }
475
+
476
+ .post-detail-drawer {
477
+ max-height: calc(100svh - 0.5rem);
478
+ overflow: hidden;
479
+ }
480
+
481
+ .overlay-post-detail {
482
+ display: grid;
483
+ min-height: 0;
484
+ }
485
+
486
+ .post-full-page-link {
487
+ display: flex;
488
+ min-height: 4.5rem;
489
+ padding: 0 4.25rem 0 1.5rem;
490
+ align-items: center;
491
+ justify-content: flex-end;
492
+ border-bottom: 1px solid var(--portal-rule);
493
+ color: var(--muted-foreground);
494
+ font-size: 0.8rem;
495
+ font-weight: 600;
496
+ text-decoration-color: transparent;
497
+ text-underline-offset: 0.25rem;
498
+ transition:
499
+ color 160ms ease,
500
+ text-decoration-color 160ms ease;
501
+ }
502
+
503
+ .post-full-page-link:hover {
504
+ color: var(--portal-ink);
505
+ text-decoration-color: currentColor;
506
+ }
507
+
508
+ .post-full-page-link svg {
509
+ width: 0.9rem;
510
+ height: 0.9rem;
511
+ margin-left: 0.5rem;
512
+ }
513
+
514
+ .post-detail-drawer .overlay-post-detail {
515
+ overflow-y: auto;
516
+ }
517
+
518
+ .draft-detail-actions {
519
+ display: flex;
520
+ justify-content: flex-end;
521
+ gap: 0.5rem;
522
+ }
523
+
524
+ .draft-detail-actions button {
525
+ min-height: 2.5rem;
526
+ padding: 0 0.85rem;
527
+ border: 1px solid var(--portal-rule);
528
+ background: transparent;
529
+ color: var(--portal-ink);
530
+ cursor: pointer;
531
+ font: inherit;
532
+ font-size: 0.8rem;
533
+ font-weight: 700;
534
+ }
535
+
536
+ .portal-shell {
537
+ min-height: 100svh;
538
+ }
539
+
540
+ .portal-header {
541
+ display: flex;
542
+ align-items: center;
543
+ justify-content: space-between;
544
+ min-height: 4.5rem;
545
+ padding: 0 5vw;
546
+ border-bottom: 1px solid var(--portal-rule);
547
+ background: color-mix(in srgb, var(--portal-paper) 92%, transparent);
548
+ backdrop-filter: blur(16px);
549
+ }
550
+
551
+ .portal-brand {
552
+ display: inline-flex;
553
+ align-items: center;
554
+ gap: 0.7rem;
555
+ color: inherit;
556
+ font-size: 1rem;
557
+ font-weight: 750;
558
+ letter-spacing: -0.03em;
559
+ text-decoration: none;
560
+ }
561
+
562
+ .portal-brand span {
563
+ display: grid;
564
+ width: 2rem;
565
+ height: 2rem;
566
+ place-items: center;
567
+ background: var(--portal-accent);
568
+ color: var(--primary-foreground);
569
+ font-size: 0.85rem;
570
+ }
571
+
572
+ .portal-header nav {
573
+ display: flex;
574
+ align-items: center;
575
+ gap: 1.25rem;
576
+ }
577
+
578
+ .portal-header nav a {
579
+ padding-block: 0.35rem;
580
+ border-bottom: 2px solid transparent;
581
+ color: var(--muted-foreground);
582
+ font-size: 0.75rem;
583
+ font-weight: 700;
584
+ letter-spacing: 0.08em;
585
+ text-decoration: none;
586
+ text-transform: uppercase;
587
+ }
588
+
589
+ .portal-header nav a:hover {
590
+ color: var(--portal-ink);
591
+ }
592
+
593
+ .portal-header nav a[aria-current="page"] {
594
+ border-bottom-color: currentColor;
595
+ color: var(--portal-ink);
596
+ }
597
+
598
+ .portal-header nav a.create-post-link {
599
+ padding: 0.65rem 0.8rem;
600
+ border: 1px solid var(--portal-ink);
601
+ background: var(--portal-ink);
602
+ color: var(--portal-paper);
603
+ }
604
+
605
+ .feedback-index {
606
+ width: min(90vw, 76rem);
607
+ margin: 0 auto;
608
+ padding: clamp(2.5rem, 6vw, 5rem) 0 6rem;
609
+ animation: page-in 480ms ease-out both;
610
+ }
611
+
612
+ .feedback-intro {
613
+ max-width: 42rem;
614
+ }
615
+
616
+ .feedback-eyebrow {
617
+ margin: 0 0 1rem;
618
+ color: var(--portal-accent);
619
+ font-size: 0.75rem;
620
+ font-weight: 750;
621
+ letter-spacing: 0.13em;
622
+ text-transform: uppercase;
623
+ }
624
+
625
+ .feedback-intro h1 {
626
+ margin: 0;
627
+ font-size: clamp(2rem, 4vw, 3.4rem);
628
+ font-weight: 650;
629
+ letter-spacing: -0.055em;
630
+ line-height: 1;
631
+ }
632
+
633
+ .feedback-deck {
634
+ max-width: 37rem;
635
+ margin: 0.85rem 0 0;
636
+ color: var(--muted-foreground);
637
+ font-size: 0.95rem;
638
+ line-height: 1.55;
639
+ }
640
+
641
+ .changelog-page {
642
+ width: min(calc(100% - 2rem), 90rem);
643
+ min-height: calc(100svh - 5rem);
644
+ margin: 0 auto;
645
+ padding: clamp(3rem, 7vw, 5rem) 0 6rem;
646
+ animation: page-in 480ms ease-out both;
647
+ }
648
+
649
+ .changelog-heading {
650
+ display: flex;
651
+ align-items: flex-start;
652
+ justify-content: space-between;
653
+ gap: 2rem;
654
+ }
655
+
656
+ .changelog-heading h1 {
657
+ margin: 0;
658
+ font-size: clamp(1.75rem, 3vw, 2.25rem);
659
+ font-weight: 650;
660
+ letter-spacing: -0.04em;
661
+ line-height: 1;
662
+ }
663
+
664
+ .changelog-heading p {
665
+ margin: 0.75rem 0 0;
666
+ color: var(--muted-foreground);
667
+ font-size: 0.95rem;
668
+ }
669
+
670
+ .changelog-toolbar {
671
+ display: flex;
672
+ align-items: center;
673
+ justify-content: space-between;
674
+ gap: 1rem;
675
+ margin: 2.5rem 0 1rem;
676
+ }
677
+
678
+ .changelog-filters {
679
+ display: grid;
680
+ grid-template-columns: repeat(4, minmax(0, 1fr));
681
+ width: min(100%, 28rem);
682
+ }
683
+
684
+ .changelog-filters button {
685
+ height: 2.5rem;
686
+ padding-inline: 1rem;
687
+ color: var(--muted-foreground);
688
+ font-size: 0.8rem;
689
+ }
690
+
691
+ .changelog-filters button[aria-pressed="true"] {
692
+ background: var(--muted);
693
+ color: var(--foreground);
694
+ }
695
+
696
+ .changelog-timeline {
697
+ position: relative;
698
+ display: grid;
699
+ gap: 0.75rem;
700
+ margin: 0;
701
+ padding: 0;
702
+ list-style: none;
703
+ }
704
+
705
+ .changelog-timeline::before {
706
+ position: absolute;
707
+ top: 1.5rem;
708
+ bottom: 4.5rem;
709
+ left: 10.875rem;
710
+ width: 1px;
711
+ background: var(--border);
712
+ content: "";
713
+ }
714
+
715
+ .changelog-timeline-entry {
716
+ position: relative;
717
+ display: grid;
718
+ grid-template-columns: 9.75rem 1.5rem minmax(0, 1fr);
719
+ align-items: start;
720
+ }
721
+
722
+ .changelog-timeline-entry > time {
723
+ padding-top: 1.1rem;
724
+ color: var(--muted-foreground);
725
+ font-size: 0.8rem;
726
+ font-variant-numeric: tabular-nums;
727
+ }
728
+
729
+ .changelog-timeline-marker {
730
+ z-index: 1;
731
+ width: 0.45rem;
732
+ height: 0.45rem;
733
+ margin: 1.35rem auto 0;
734
+ border: 2px solid var(--background);
735
+ border-radius: 50%;
736
+ background: color-mix(
737
+ in srgb,
738
+ var(--muted-foreground) 55%,
739
+ var(--background)
740
+ );
741
+ box-sizing: content-box;
742
+ }
743
+
744
+ .changelog-timeline-entry > article {
745
+ min-width: 0;
746
+ scroll-margin-top: 6rem;
747
+ border: 1px solid var(--border);
748
+ background: color-mix(in srgb, var(--card) 36%, transparent);
749
+ transition:
750
+ border-color 180ms ease,
751
+ background-color 180ms ease;
752
+ }
753
+
754
+ .changelog-timeline-entry > article:hover,
755
+ .changelog-timeline-entry > article:target {
756
+ border-color: color-mix(in srgb, var(--foreground) 28%, var(--border));
757
+ background: color-mix(in srgb, var(--card) 72%, transparent);
758
+ }
759
+
760
+ .changelog-timeline-entry > article:target {
761
+ outline: 1px solid color-mix(in srgb, var(--ring) 65%, transparent);
762
+ outline-offset: 3px;
763
+ }
764
+
765
+ .changelog-entry-layout {
766
+ padding: 1rem 1.5rem;
767
+ }
768
+
769
+ .changelog-entry-layout.has-image {
770
+ display: grid;
771
+ grid-template-columns: minmax(17rem, 1fr) minmax(20rem, 0.8fr);
772
+ gap: clamp(1.5rem, 4vw, 4rem);
773
+ align-items: center;
774
+ min-height: 16rem;
775
+ }
776
+
777
+ .changelog-entry-copy {
778
+ min-width: 0;
779
+ }
780
+
781
+ .changelog-labels {
782
+ display: flex;
783
+ flex-wrap: wrap;
784
+ gap: 0.4rem;
785
+ margin-bottom: 0.7rem;
786
+ }
787
+
788
+ .changelog-label {
789
+ border-color: color-mix(in srgb, var(--foreground) 12%, transparent);
790
+ background: color-mix(in srgb, var(--muted) 72%, transparent);
791
+ color: var(--muted-foreground);
792
+ }
793
+
794
+ .changelog-label > span {
795
+ width: 0.45rem;
796
+ height: 0.45rem;
797
+ border-radius: 50%;
798
+ background: currentColor;
799
+ }
800
+
801
+ .changelog-label.is-new {
802
+ background: color-mix(in srgb, var(--changelog-new) 12%, transparent);
803
+ color: var(--changelog-new);
804
+ }
805
+
806
+ .changelog-label.is-improved {
807
+ background: color-mix(in srgb, var(--changelog-improved) 12%, transparent);
808
+ color: var(--changelog-improved);
809
+ }
810
+
811
+ .changelog-label.is-fixed {
812
+ background: color-mix(in srgb, var(--destructive) 12%, transparent);
813
+ color: var(--destructive);
814
+ }
815
+
816
+ .changelog-entry-title {
817
+ display: flex;
818
+ align-items: center;
819
+ gap: 0.6rem;
820
+ }
821
+
822
+ .changelog-entry-title h2 {
823
+ margin: 0;
824
+ font-size: 1.1rem;
825
+ font-weight: 650;
826
+ letter-spacing: -0.025em;
827
+ }
828
+
829
+ .changelog-entry-title a {
830
+ display: inline-grid;
831
+ flex: none;
832
+ width: 1.75rem;
833
+ height: 1.75rem;
834
+ place-items: center;
835
+ color: var(--muted-foreground);
836
+ opacity: 0.55;
837
+ transition:
838
+ color 160ms ease,
839
+ opacity 160ms ease,
840
+ transform 160ms ease;
841
+ }
842
+
843
+ .changelog-entry-title a:hover,
844
+ .changelog-entry-title a:focus-visible {
845
+ color: var(--foreground);
846
+ opacity: 1;
847
+ transform: translateY(-1px);
848
+ }
849
+
850
+ .changelog-entry-title svg {
851
+ width: 0.9rem;
852
+ height: 0.9rem;
853
+ }
854
+
855
+ .changelog-entry-summary {
856
+ margin: 0.45rem 0 0;
857
+ color: var(--muted-foreground);
858
+ font-size: 0.9rem;
859
+ line-height: 1.5;
860
+ }
861
+
862
+ .changelog-entry-body {
863
+ margin-top: 0.7rem;
864
+ color: var(--muted-foreground);
865
+ font-size: 0.86rem;
866
+ line-height: 1.55;
867
+ }
868
+
869
+ .changelog-entry-body p,
870
+ .changelog-entry-body ul {
871
+ margin: 0;
872
+ }
873
+
874
+ .changelog-entry-body ul {
875
+ padding-left: 1.25rem;
876
+ }
877
+
878
+ .changelog-entry-layout img {
879
+ display: block;
880
+ width: 100%;
881
+ border: 1px solid var(--border);
882
+ background: var(--background);
883
+ }
884
+
885
+ .changelog-load-more {
886
+ display: flex;
887
+ justify-content: center;
888
+ margin: 1rem 0 0 11.25rem;
889
+ }
890
+
891
+ @media (max-width: 800px) {
892
+ .changelog-page {
893
+ width: min(calc(100% - 2rem), 42rem);
894
+ padding-top: 5rem;
895
+ }
896
+
897
+ .changelog-heading {
898
+ align-items: stretch;
899
+ flex-direction: column;
900
+ }
901
+
902
+ .changelog-heading button,
903
+ .changelog-toolbar button {
904
+ width: 100%;
905
+ }
906
+
907
+ .changelog-toolbar {
908
+ display: grid;
909
+ grid-template-columns: minmax(0, 1fr);
910
+ margin-top: 1rem;
911
+ }
912
+
913
+ .changelog-filters {
914
+ width: 100%;
915
+ }
916
+
917
+ .changelog-filters button {
918
+ height: 2.75rem;
919
+ min-width: 0;
920
+ padding-inline: 0.45rem;
921
+ font-size: 0.72rem;
922
+ }
923
+
924
+ .changelog-timeline::before {
925
+ top: 3rem;
926
+ bottom: 3rem;
927
+ left: 0.35rem;
928
+ }
929
+
930
+ .changelog-timeline-entry {
931
+ grid-template-columns: 0.75rem minmax(0, 1fr);
932
+ column-gap: 0.75rem;
933
+ }
934
+
935
+ .changelog-timeline-entry > time {
936
+ grid-column: 2;
937
+ padding: 0 0 0.55rem;
938
+ }
939
+
940
+ .changelog-timeline-marker {
941
+ grid-column: 1;
942
+ grid-row: 1 / span 2;
943
+ margin-top: 0.25rem;
944
+ }
945
+
946
+ .changelog-timeline-entry > article {
947
+ grid-column: 2;
948
+ }
949
+
950
+ .changelog-entry-layout,
951
+ .changelog-entry-layout.has-image {
952
+ display: grid;
953
+ grid-template-columns: minmax(0, 1fr);
954
+ gap: 1.25rem;
955
+ min-height: 0;
956
+ padding: 1.1rem;
957
+ }
958
+
959
+ .changelog-load-more {
960
+ margin-left: 1.5rem;
961
+ }
962
+
963
+ .changelog-load-more button {
964
+ width: 100%;
965
+ min-width: 0;
966
+ }
967
+ }
968
+
969
+ .theme-control {
970
+ display: grid;
971
+ gap: 0.4rem;
972
+ color: var(--muted-foreground);
973
+ font-size: 0.75rem;
974
+ font-weight: 700;
975
+ }
976
+
977
+ .theme-control select {
978
+ min-height: 2.5rem;
979
+ border: 1px solid var(--portal-rule);
980
+ background: var(--portal-paper);
981
+ color: var(--portal-ink);
982
+ }
983
+
984
+ .feedback-filters {
985
+ display: grid;
986
+ grid-template-columns: repeat(2, minmax(0, 1fr)) auto;
987
+ gap: 1rem;
988
+ align-items: end;
989
+ margin: clamp(3rem, 7vw, 6rem) 0 0;
990
+ padding: 1.35rem 0;
991
+ border-block: 1px solid var(--portal-rule);
992
+ }
993
+
994
+ .feedback-filters label {
995
+ display: grid;
996
+ gap: 0.55rem;
997
+ }
998
+
999
+ .feedback-filters label > span {
1000
+ color: var(--muted-foreground);
1001
+ font-size: 0.68rem;
1002
+ font-weight: 700;
1003
+ letter-spacing: 0.08em;
1004
+ text-transform: uppercase;
1005
+ }
1006
+
1007
+ .feedback-filters select,
1008
+ .feedback-filters button {
1009
+ min-height: 2.8rem;
1010
+ border: 1px solid var(--input);
1011
+ border-radius: 0;
1012
+ background: transparent;
1013
+ color: var(--portal-ink);
1014
+ font: inherit;
1015
+ }
1016
+
1017
+ .feedback-filters select {
1018
+ width: 100%;
1019
+ padding: 0 2.5rem 0 0.8rem;
1020
+ }
1021
+
1022
+ .feedback-filters button {
1023
+ padding: 0 1.35rem;
1024
+ border-color: var(--portal-ink);
1025
+ background: var(--portal-ink);
1026
+ color: var(--primary-foreground);
1027
+ cursor: pointer;
1028
+ font-size: 0.82rem;
1029
+ font-weight: 700;
1030
+ transition:
1031
+ background-color 160ms ease,
1032
+ transform 160ms ease;
1033
+ }
1034
+
1035
+ .feedback-filters button:hover {
1036
+ background: var(--portal-accent);
1037
+ transform: translateY(-2px);
1038
+ }
1039
+
1040
+ .feedback-results {
1041
+ padding-top: 3rem;
1042
+ }
1043
+
1044
+ .feedback-feed-skeleton .animate-pulse,
1045
+ .post-detail-skeleton .animate-pulse {
1046
+ border-radius: 0;
1047
+ }
1048
+
1049
+ .feedback-skeleton-heading {
1050
+ width: min(34rem, 80vw);
1051
+ height: clamp(2.5rem, 7vw, 5.5rem);
1052
+ }
1053
+
1054
+ .feedback-skeleton-deck {
1055
+ width: min(32rem, 70vw);
1056
+ height: 1.25rem;
1057
+ margin-top: 1.25rem;
1058
+ }
1059
+
1060
+ .feedback-skeleton-control {
1061
+ width: 9rem;
1062
+ height: 2.75rem;
1063
+ }
1064
+
1065
+ .feedback-skeleton-section-heading,
1066
+ .feedback-skeleton-meta {
1067
+ width: 8rem;
1068
+ height: 0.75rem;
1069
+ }
1070
+
1071
+ .feedback-skeleton-row {
1072
+ display: grid;
1073
+ gap: 0.8rem;
1074
+ padding: clamp(1.5rem, 3vw, 2.4rem) 0;
1075
+ }
1076
+
1077
+ .feedback-skeleton-title {
1078
+ width: min(30rem, 70vw);
1079
+ height: 2rem;
1080
+ }
1081
+
1082
+ .feedback-skeleton-copy {
1083
+ width: min(42rem, 80vw);
1084
+ height: 1rem;
1085
+ }
1086
+
1087
+ .post-detail-skeleton-back {
1088
+ width: 8rem;
1089
+ height: 1rem;
1090
+ }
1091
+
1092
+ .post-detail-skeleton-meta {
1093
+ width: 12rem;
1094
+ height: 0.8rem;
1095
+ }
1096
+
1097
+ .post-detail-skeleton-title {
1098
+ width: min(44rem, 75vw);
1099
+ height: clamp(3rem, 7vw, 6rem);
1100
+ margin-top: 1.25rem;
1101
+ }
1102
+
1103
+ .post-detail-skeleton-copy {
1104
+ width: min(52rem, 80vw);
1105
+ height: 1rem;
1106
+ margin-top: 2rem;
1107
+ }
1108
+
1109
+ .post-detail-skeleton-copy-short {
1110
+ width: min(35rem, 60vw);
1111
+ margin-top: 0.75rem;
1112
+ }
1113
+
1114
+ .creation-skeleton-eyebrow {
1115
+ width: 7rem;
1116
+ height: 0.75rem;
1117
+ }
1118
+
1119
+ .creation-skeleton-heading {
1120
+ width: min(22rem, 70vw);
1121
+ height: clamp(3rem, 6vw, 5rem);
1122
+ margin-top: 1rem;
1123
+ }
1124
+
1125
+ .creation-skeleton-copy {
1126
+ width: min(26rem, 75vw);
1127
+ height: 3rem;
1128
+ margin-top: 1.5rem;
1129
+ }
1130
+
1131
+ .creation-skeleton-field,
1132
+ .creation-skeleton-textarea,
1133
+ .creation-skeleton-action {
1134
+ width: 100%;
1135
+ height: 3rem;
1136
+ }
1137
+
1138
+ .creation-skeleton-textarea {
1139
+ height: 9rem;
1140
+ }
1141
+
1142
+ .creation-skeleton-action {
1143
+ width: 8rem;
1144
+ }
1145
+
1146
+ .feedback-results-heading {
1147
+ display: flex;
1148
+ align-items: baseline;
1149
+ justify-content: space-between;
1150
+ gap: 1rem;
1151
+ padding-bottom: 1rem;
1152
+ }
1153
+
1154
+ .feedback-results-heading h2 {
1155
+ margin: 0;
1156
+ font-size: 1.25rem;
1157
+ letter-spacing: -0.035em;
1158
+ }
1159
+
1160
+ .feedback-results-heading span {
1161
+ color: var(--muted-foreground);
1162
+ font-size: 0.75rem;
1163
+ }
1164
+
1165
+ .feedback-list {
1166
+ margin: 0;
1167
+ padding: 0;
1168
+ border-top: 1px solid var(--portal-ink);
1169
+ list-style: none;
1170
+ }
1171
+
1172
+ .feedback-list li {
1173
+ border-bottom: 1px solid var(--portal-rule);
1174
+ }
1175
+
1176
+ .post-link {
1177
+ display: block;
1178
+ color: inherit;
1179
+ text-decoration: none;
1180
+ }
1181
+
1182
+ .feedback-list article {
1183
+ padding: clamp(1.5rem, 3vw, 2.4rem) 0;
1184
+ transition: transform 180ms ease;
1185
+ }
1186
+
1187
+ .feedback-list li:hover article {
1188
+ transform: translateX(0.45rem);
1189
+ }
1190
+
1191
+ .feedback-meta {
1192
+ display: flex;
1193
+ flex-wrap: wrap;
1194
+ gap: 0.5rem 1rem;
1195
+ color: var(--muted-foreground);
1196
+ font-size: 0.7rem;
1197
+ font-weight: 650;
1198
+ letter-spacing: 0.045em;
1199
+ text-transform: uppercase;
1200
+ }
1201
+
1202
+ .feedback-meta span:nth-child(2) {
1203
+ color: var(--portal-accent);
1204
+ }
1205
+
1206
+ .feedback-list h3 {
1207
+ margin: 0.8rem 0 0;
1208
+ font-size: clamp(1.35rem, 2.5vw, 2.15rem);
1209
+ font-weight: 620;
1210
+ letter-spacing: -0.045em;
1211
+ }
1212
+
1213
+ .feedback-list article > p {
1214
+ max-width: 47rem;
1215
+ margin: 0.75rem 0 0;
1216
+ color: var(--muted-foreground);
1217
+ line-height: 1.65;
1218
+ }
1219
+
1220
+ .feedback-empty {
1221
+ padding: 5rem 0;
1222
+ border-block: 1px solid var(--portal-rule);
1223
+ text-align: center;
1224
+ }
1225
+
1226
+ .feedback-empty p {
1227
+ margin: 0 0 1rem;
1228
+ font-size: clamp(1.4rem, 3vw, 2rem);
1229
+ letter-spacing: -0.04em;
1230
+ }
1231
+
1232
+ .feedback-empty a,
1233
+ .feedback-next {
1234
+ color: var(--portal-accent);
1235
+ font-weight: 700;
1236
+ text-underline-offset: 0.25em;
1237
+ }
1238
+
1239
+ .feedback-next {
1240
+ display: inline-flex;
1241
+ align-items: center;
1242
+ gap: 0.6rem;
1243
+ margin-top: 2rem;
1244
+ text-decoration: none;
1245
+ }
1246
+
1247
+ .feedback-next svg {
1248
+ width: 1rem;
1249
+ transition: transform 160ms ease;
1250
+ }
1251
+
1252
+ .feedback-next:hover svg {
1253
+ transform: translateX(0.35rem);
1254
+ }
1255
+
1256
+ .roadmap-page {
1257
+ width: min(90vw, 90rem);
1258
+ margin: 0 auto;
1259
+ padding: clamp(3.5rem, 8vw, 8rem) 0 6rem;
1260
+ animation: page-in 480ms ease-out both;
1261
+ }
1262
+
1263
+ .roadmap-intro {
1264
+ display: grid;
1265
+ grid-template-columns: minmax(0, 1fr) minmax(18rem, 0.55fr);
1266
+ gap: 2rem;
1267
+ align-items: end;
1268
+ }
1269
+
1270
+ .roadmap-intro .feedback-eyebrow {
1271
+ grid-column: 1 / -1;
1272
+ margin-bottom: -1rem;
1273
+ }
1274
+
1275
+ .roadmap-intro h1 {
1276
+ max-width: 12ch;
1277
+ margin: 0;
1278
+ font-size: clamp(3rem, 7vw, 6.5rem);
1279
+ font-weight: 650;
1280
+ letter-spacing: -0.075em;
1281
+ line-height: 0.94;
1282
+ }
1283
+
1284
+ .roadmap-intro > p:last-child {
1285
+ margin: 0;
1286
+ color: var(--muted-foreground);
1287
+ font-size: clamp(1rem, 1.5vw, 1.2rem);
1288
+ line-height: 1.65;
1289
+ }
1290
+
1291
+ .roadmap-groups {
1292
+ display: grid;
1293
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1294
+ gap: 1px;
1295
+ margin-top: clamp(4rem, 9vw, 8rem);
1296
+ border: 1px solid var(--portal-ink);
1297
+ background: var(--portal-ink);
1298
+ }
1299
+
1300
+ .roadmap-group {
1301
+ min-width: 0;
1302
+ background: var(--portal-paper);
1303
+ }
1304
+
1305
+ .roadmap-group > header {
1306
+ display: flex;
1307
+ align-items: baseline;
1308
+ justify-content: space-between;
1309
+ gap: 1rem;
1310
+ padding: 1.15rem 1.25rem;
1311
+ border-bottom: 1px solid var(--portal-ink);
1312
+ }
1313
+
1314
+ .roadmap-group h2 {
1315
+ margin: 0;
1316
+ font-size: 0.82rem;
1317
+ letter-spacing: 0.08em;
1318
+ text-transform: uppercase;
1319
+ }
1320
+
1321
+ .roadmap-group > header span {
1322
+ color: var(--portal-accent);
1323
+ font-size: 0.75rem;
1324
+ font-weight: 750;
1325
+ }
1326
+
1327
+ .roadmap-list {
1328
+ margin: 0;
1329
+ padding: 0;
1330
+ list-style: none;
1331
+ }
1332
+
1333
+ .roadmap-list li + li {
1334
+ border-top: 1px solid var(--portal-rule);
1335
+ }
1336
+
1337
+ .roadmap-list a {
1338
+ display: block;
1339
+ color: inherit;
1340
+ text-decoration: none;
1341
+ }
1342
+
1343
+ .roadmap-list article {
1344
+ padding: 1.5rem 1.25rem;
1345
+ transition: background-color 160ms ease;
1346
+ }
1347
+
1348
+ .roadmap-list a:hover article {
1349
+ background: color-mix(in srgb, var(--portal-accent) 6%, transparent);
1350
+ }
1351
+
1352
+ .roadmap-item-meta {
1353
+ display: flex;
1354
+ flex-wrap: wrap;
1355
+ gap: 0.45rem 0.8rem;
1356
+ color: var(--muted-foreground);
1357
+ font-size: 0.65rem;
1358
+ font-weight: 700;
1359
+ letter-spacing: 0.045em;
1360
+ text-transform: uppercase;
1361
+ }
1362
+
1363
+ .roadmap-item-meta span {
1364
+ color: var(--portal-accent);
1365
+ }
1366
+
1367
+ .roadmap-list h3 {
1368
+ margin: 0.8rem 0 0;
1369
+ font-size: clamp(1.2rem, 2vw, 1.65rem);
1370
+ font-weight: 640;
1371
+ letter-spacing: -0.04em;
1372
+ }
1373
+
1374
+ .roadmap-list article > p {
1375
+ display: -webkit-box;
1376
+ overflow: hidden;
1377
+ margin: 0.65rem 0 0;
1378
+ -webkit-box-orient: vertical;
1379
+ color: var(--muted-foreground);
1380
+ line-height: 1.55;
1381
+ -webkit-line-clamp: 3;
1382
+ }
1383
+
1384
+ .roadmap-empty {
1385
+ margin: 0;
1386
+ padding: 3.5rem 1.25rem;
1387
+ color: var(--muted-foreground);
1388
+ font-size: 0.86rem;
1389
+ line-height: 1.5;
1390
+ }
1391
+
1392
+ .roadmap-skeleton-count {
1393
+ width: 1.5rem;
1394
+ height: 0.75rem;
1395
+ }
1396
+
1397
+ .roadmap-skeleton-card {
1398
+ display: grid;
1399
+ gap: 0.75rem;
1400
+ padding: 1.5rem 1.25rem;
1401
+ }
1402
+
1403
+ .roadmap-skeleton-meta {
1404
+ width: 55%;
1405
+ height: 0.65rem;
1406
+ }
1407
+
1408
+ .roadmap-skeleton-title {
1409
+ width: 80%;
1410
+ height: 1.65rem;
1411
+ }
1412
+
1413
+ .roadmap-skeleton-copy {
1414
+ width: 100%;
1415
+ height: 0.85rem;
1416
+ }
1417
+
1418
+ .roadmap-skeleton-copy-short {
1419
+ width: 70%;
1420
+ }
1421
+
1422
+ .feedback-detail {
1423
+ width: min(90vw, 76rem);
1424
+ margin: 0 auto;
1425
+ padding: clamp(2.5rem, 6vw, 5rem) 0 6rem;
1426
+ animation: page-in 480ms ease-out both;
1427
+ }
1428
+
1429
+ .feedback-detail-back {
1430
+ display: inline-flex;
1431
+ align-items: center;
1432
+ gap: 0.55rem;
1433
+ color: var(--portal-ink);
1434
+ font-size: 0.78rem;
1435
+ font-weight: 700;
1436
+ text-decoration: none;
1437
+ }
1438
+
1439
+ .feedback-detail-back svg {
1440
+ width: 1rem;
1441
+ transition: transform 160ms ease;
1442
+ }
1443
+
1444
+ .feedback-detail-back:hover svg {
1445
+ transform: translateX(-0.3rem);
1446
+ }
1447
+
1448
+ .feedback-detail article {
1449
+ max-width: 62rem;
1450
+ margin-top: clamp(4rem, 9vw, 8rem);
1451
+ }
1452
+
1453
+ .feedback-detail-meta {
1454
+ display: flex;
1455
+ flex-wrap: wrap;
1456
+ gap: 0.75rem 1.25rem;
1457
+ color: var(--portal-accent);
1458
+ font-size: 0.72rem;
1459
+ font-weight: 750;
1460
+ letter-spacing: 0.08em;
1461
+ text-transform: uppercase;
1462
+ }
1463
+
1464
+ .feedback-detail-meta span + span {
1465
+ color: var(--muted-foreground);
1466
+ }
1467
+
1468
+ .feedback-detail h1 {
1469
+ max-width: 14ch;
1470
+ margin: 1.25rem 0 0;
1471
+ font-size: clamp(3rem, 7vw, 6.5rem);
1472
+ font-weight: 650;
1473
+ letter-spacing: -0.075em;
1474
+ line-height: 0.94;
1475
+ }
1476
+
1477
+ .feedback-detail-description {
1478
+ max-width: 48rem;
1479
+ margin: clamp(2rem, 5vw, 4rem) 0 0;
1480
+ color: var(--muted-foreground);
1481
+ font-size: clamp(1.15rem, 2vw, 1.5rem);
1482
+ line-height: 1.75;
1483
+ white-space: pre-wrap;
1484
+ }
1485
+
1486
+ .feedback-detail-dates {
1487
+ display: flex;
1488
+ gap: clamp(2rem, 7vw, 6rem);
1489
+ margin: clamp(3rem, 6vw, 5rem) 0 0;
1490
+ padding-top: 1.25rem;
1491
+ border-top: 1px solid var(--portal-rule);
1492
+ }
1493
+
1494
+ .feedback-detail-dates div {
1495
+ display: grid;
1496
+ gap: 0.35rem;
1497
+ }
1498
+
1499
+ .feedback-detail-dates dt {
1500
+ color: var(--muted-foreground);
1501
+ font-size: 0.68rem;
1502
+ font-weight: 700;
1503
+ letter-spacing: 0.08em;
1504
+ text-transform: uppercase;
1505
+ }
1506
+
1507
+ .feedback-detail-dates dd {
1508
+ margin: 0;
1509
+ font-size: 0.85rem;
1510
+ font-weight: 650;
1511
+ }
1512
+
1513
+ .public-post-detail {
1514
+ width: min(90vw, 70rem);
1515
+ padding: clamp(2rem, 5vw, 4rem) 0 5rem;
1516
+ }
1517
+
1518
+ .public-post-detail[data-display="overlay"] {
1519
+ width: 100%;
1520
+ margin: 0;
1521
+ padding: 0;
1522
+ animation: none;
1523
+ }
1524
+
1525
+ .public-post-detail .post-detail-layout {
1526
+ display: grid;
1527
+ max-width: none;
1528
+ grid-template-columns: minmax(0, 1fr) minmax(17rem, 0.42fr);
1529
+ margin-top: 1.5rem;
1530
+ border: 1px solid var(--portal-rule);
1531
+ background: color-mix(in srgb, var(--card) 55%, var(--background));
1532
+ }
1533
+
1534
+ .public-post-detail[data-display="overlay"] .post-detail-layout {
1535
+ margin-top: 0;
1536
+ border: 0;
1537
+ }
1538
+
1539
+ .post-detail-primary,
1540
+ .post-detail-sidebar {
1541
+ min-width: 0;
1542
+ padding: clamp(1.5rem, 4vw, 2.5rem);
1543
+ }
1544
+
1545
+ .post-detail-sidebar {
1546
+ border-left: 1px solid var(--portal-rule);
1547
+ background: color-mix(in srgb, var(--muted) 16%, transparent);
1548
+ }
1549
+
1550
+ .public-post-detail .feedback-detail-meta {
1551
+ display: flex;
1552
+ gap: 0.5rem;
1553
+ color: inherit;
1554
+ font-size: inherit;
1555
+ letter-spacing: normal;
1556
+ text-transform: none;
1557
+ }
1558
+
1559
+ .public-post-detail .feedback-detail-meta [data-status="Planned"],
1560
+ .public-post-detail .post-detail-details [data-status="Planned"] {
1561
+ border-color: color-mix(in srgb, var(--status-planned) 40%, transparent);
1562
+ background: color-mix(in srgb, var(--status-planned) 14%, transparent);
1563
+ color: var(--status-planned);
1564
+ }
1565
+
1566
+ .public-post-detail .feedback-detail-meta [data-status="In Progress"],
1567
+ .public-post-detail .post-detail-details [data-status="In Progress"] {
1568
+ border-color: color-mix(in srgb, var(--status-in-progress) 40%, transparent);
1569
+ background: color-mix(in srgb, var(--status-in-progress) 14%, transparent);
1570
+ color: var(--status-in-progress);
1571
+ }
1572
+
1573
+ .public-post-detail .feedback-detail-meta [data-status="Shipped"],
1574
+ .public-post-detail .post-detail-details [data-status="Shipped"] {
1575
+ border-color: color-mix(in srgb, var(--status-shipped) 40%, transparent);
1576
+ background: color-mix(in srgb, var(--status-shipped) 14%, transparent);
1577
+ color: var(--status-shipped);
1578
+ }
1579
+
1580
+ .public-post-detail h1 {
1581
+ max-width: 22ch;
1582
+ margin: 1.5rem 0 0;
1583
+ font-size: clamp(2rem, 4vw, 3rem);
1584
+ font-weight: 650;
1585
+ letter-spacing: -0.05em;
1586
+ line-height: 1.05;
1587
+ }
1588
+
1589
+ .public-post-detail .feedback-detail-description {
1590
+ max-width: 45rem;
1591
+ margin: 0.75rem 0 0;
1592
+ color: var(--muted-foreground);
1593
+ font-size: clamp(0.95rem, 1.4vw, 1.05rem);
1594
+ line-height: 1.65;
1595
+ }
1596
+
1597
+ .post-detail-engagement {
1598
+ display: flex;
1599
+ align-items: center;
1600
+ justify-content: space-between;
1601
+ gap: 1rem;
1602
+ margin-top: 1.75rem;
1603
+ }
1604
+
1605
+ .post-detail-summary-actions {
1606
+ margin-top: 1.25rem;
1607
+ }
1608
+
1609
+ .post-detail-engagement > span {
1610
+ display: inline-flex;
1611
+ min-height: 2.75rem;
1612
+ align-items: center;
1613
+ gap: 0.6rem;
1614
+ color: var(--muted-foreground);
1615
+ font-size: 0.85rem;
1616
+ }
1617
+
1618
+ .post-detail-engagement > span:first-child {
1619
+ min-width: 5rem;
1620
+ justify-content: center;
1621
+ border: 1px solid var(--portal-rule);
1622
+ color: var(--portal-ink);
1623
+ }
1624
+
1625
+ .post-detail-engagement svg {
1626
+ width: 1rem;
1627
+ height: 1rem;
1628
+ }
1629
+
1630
+ .post-detail-comments {
1631
+ margin-top: 1.75rem;
1632
+ padding-top: 1.75rem;
1633
+ border-top: 1px solid var(--portal-rule);
1634
+ }
1635
+
1636
+ .post-detail-comments > h2,
1637
+ .post-detail-sidebar > h2 {
1638
+ margin: 0;
1639
+ font-size: 1rem;
1640
+ font-weight: 650;
1641
+ letter-spacing: -0.02em;
1642
+ }
1643
+
1644
+ .post-detail-comments-empty {
1645
+ min-height: 13rem;
1646
+ margin-top: 1.25rem;
1647
+ border: 1px dashed var(--portal-rule);
1648
+ background: color-mix(in srgb, var(--muted) 12%, transparent);
1649
+ }
1650
+
1651
+ .comment-threads {
1652
+ margin-top: 1.25rem;
1653
+ border-block: 1px solid var(--portal-rule);
1654
+ }
1655
+
1656
+ .comment-thread + .comment-thread {
1657
+ border-top: 1px solid var(--portal-rule);
1658
+ }
1659
+
1660
+ .comment {
1661
+ padding: 1.15rem 0;
1662
+ }
1663
+
1664
+ .comment + .comment {
1665
+ border-top: 1px solid color-mix(in srgb, var(--portal-rule) 70%, transparent);
1666
+ }
1667
+
1668
+ .comment[data-reply="true"] {
1669
+ margin-left: 2rem;
1670
+ padding-left: 1rem;
1671
+ border-left: 2px solid var(--portal-rule);
1672
+ }
1673
+
1674
+ .comment-header {
1675
+ display: flex;
1676
+ align-items: center;
1677
+ justify-content: space-between;
1678
+ gap: 0.75rem;
1679
+ }
1680
+
1681
+ .comment-author {
1682
+ display: flex;
1683
+ min-width: 0;
1684
+ flex-wrap: wrap;
1685
+ align-items: center;
1686
+ gap: 0.45rem;
1687
+ }
1688
+
1689
+ .comment-author strong {
1690
+ overflow: hidden;
1691
+ font-size: 0.85rem;
1692
+ font-weight: 650;
1693
+ text-overflow: ellipsis;
1694
+ white-space: nowrap;
1695
+ }
1696
+
1697
+ .comment-author span {
1698
+ padding: 0.1rem 0.35rem;
1699
+ border: 1px solid var(--portal-rule);
1700
+ color: var(--muted-foreground);
1701
+ font-size: 0.65rem;
1702
+ line-height: 1.25;
1703
+ }
1704
+
1705
+ .comment-header time {
1706
+ flex: none;
1707
+ color: var(--muted-foreground);
1708
+ font-size: 0.72rem;
1709
+ font-variant-numeric: tabular-nums;
1710
+ }
1711
+
1712
+ .comment-body {
1713
+ margin: 0.6rem 0 0;
1714
+ color: var(--foreground);
1715
+ font-size: 0.9rem;
1716
+ line-height: 1.6;
1717
+ overflow-wrap: anywhere;
1718
+ }
1719
+
1720
+ .comment-actions {
1721
+ display: flex;
1722
+ flex-wrap: wrap;
1723
+ justify-content: flex-end;
1724
+ gap: 0.25rem;
1725
+ margin-top: 0.65rem;
1726
+ }
1727
+
1728
+ .profile-gate {
1729
+ min-height: 13rem;
1730
+ margin-top: 1.25rem;
1731
+ border: 1px dashed var(--portal-rule);
1732
+ background: color-mix(in srgb, var(--muted) 14%, transparent);
1733
+ }
1734
+
1735
+ .comment-composer {
1736
+ display: grid;
1737
+ gap: 0.75rem;
1738
+ margin-top: 1.25rem;
1739
+ padding: 1rem;
1740
+ border: 1px solid
1741
+ color-mix(in srgb, var(--foreground) 24%, var(--portal-rule));
1742
+ background: var(--card);
1743
+ box-shadow: 0 0 0 1px color-mix(in srgb, var(--background) 70%, transparent);
1744
+ }
1745
+
1746
+ .comment-composer-label {
1747
+ font-size: 0.9rem;
1748
+ font-weight: 650;
1749
+ }
1750
+
1751
+ .comment-composer-hint {
1752
+ margin: -0.35rem 0 0;
1753
+ color: var(--muted-foreground);
1754
+ font-size: 0.75rem;
1755
+ line-height: 1.45;
1756
+ }
1757
+
1758
+ .comment-composer-input {
1759
+ min-height: 7rem;
1760
+ resize: vertical;
1761
+ border-color: color-mix(in srgb, var(--foreground) 28%, var(--portal-rule));
1762
+ background: var(--background);
1763
+ font-size: 0.9rem;
1764
+ line-height: 1.5;
1765
+ }
1766
+
1767
+ .comment-composer-input:focus-visible {
1768
+ border-color: var(--portal-accent);
1769
+ background: var(--card);
1770
+ }
1771
+
1772
+ .comment-composer-actions {
1773
+ display: flex;
1774
+ flex-wrap: wrap;
1775
+ gap: 0.5rem;
1776
+ justify-content: flex-end;
1777
+ }
1778
+
1779
+ .post-detail-details {
1780
+ display: grid;
1781
+ gap: 1.25rem;
1782
+ margin: 1.5rem 0 0;
1783
+ }
1784
+
1785
+ .post-detail-details > div {
1786
+ display: grid;
1787
+ grid-template-columns: minmax(5rem, 0.75fr) minmax(0, 1fr);
1788
+ gap: 1rem;
1789
+ align-items: center;
1790
+ }
1791
+
1792
+ .post-detail-details dt {
1793
+ color: var(--muted-foreground);
1794
+ font-size: 0.8rem;
1795
+ }
1796
+
1797
+ .post-detail-details dd {
1798
+ min-width: 0;
1799
+ margin: 0;
1800
+ font-size: 0.8rem;
1801
+ font-weight: 550;
1802
+ }
1803
+
1804
+ .post-detail-details time {
1805
+ white-space: nowrap;
1806
+ }
1807
+
1808
+ .feedback-detail-missing {
1809
+ display: flex;
1810
+ min-height: calc(100svh - 4.5rem);
1811
+ flex-direction: column;
1812
+ align-items: flex-start;
1813
+ justify-content: center;
1814
+ padding-block: 3rem;
1815
+ }
1816
+
1817
+ .feedback-detail-missing h1 {
1818
+ max-width: 11ch;
1819
+ }
1820
+
1821
+ .feedback-detail-missing > p:not(.feedback-eyebrow) {
1822
+ max-width: 34rem;
1823
+ margin: 1.5rem 0 2rem;
1824
+ color: var(--muted-foreground);
1825
+ font-size: 1.05rem;
1826
+ }
1827
+
1828
+ .public-error {
1829
+ display: flex;
1830
+ width: min(90vw, 76rem);
1831
+ min-height: calc(100svh - 4.5rem);
1832
+ margin: 0 auto;
1833
+ padding-block: 3rem;
1834
+ flex-direction: column;
1835
+ align-items: flex-start;
1836
+ justify-content: center;
1837
+ }
1838
+
1839
+ .public-error h1 {
1840
+ max-width: 12ch;
1841
+ margin: 0;
1842
+ font-size: clamp(3rem, 7vw, 6.5rem);
1843
+ font-weight: 650;
1844
+ letter-spacing: -0.075em;
1845
+ line-height: 0.94;
1846
+ }
1847
+
1848
+ .public-error > p:not(.feedback-eyebrow) {
1849
+ max-width: 38rem;
1850
+ margin: 1.5rem 0 2rem;
1851
+ color: var(--muted-foreground);
1852
+ font-size: 1.05rem;
1853
+ line-height: 1.65;
1854
+ }
1855
+
1856
+ .public-error-actions {
1857
+ display: flex;
1858
+ flex-wrap: wrap;
1859
+ gap: 0.75rem;
1860
+ }
1861
+
1862
+ .public-error-actions button,
1863
+ .public-error-actions a {
1864
+ display: inline-flex;
1865
+ min-height: 3rem;
1866
+ padding: 0 1.25rem;
1867
+ align-items: center;
1868
+ border: 1px solid var(--portal-ink);
1869
+ border-radius: 0;
1870
+ background: var(--portal-ink);
1871
+ color: var(--primary-foreground);
1872
+ cursor: pointer;
1873
+ font: inherit;
1874
+ font-size: 0.82rem;
1875
+ font-weight: 750;
1876
+ text-decoration: none;
1877
+ }
1878
+
1879
+ .public-error-actions a {
1880
+ background: transparent;
1881
+ color: var(--portal-ink);
1882
+ }
1883
+
1884
+ .portal-loading {
1885
+ display: flex;
1886
+ min-height: calc(100svh - 4.5rem);
1887
+ align-items: center;
1888
+ justify-content: center;
1889
+ gap: 0.75rem;
1890
+ color: var(--muted-foreground);
1891
+ font-size: 0.85rem;
1892
+ }
1893
+
1894
+ .portal-loading svg {
1895
+ width: 1.1rem;
1896
+ animation: spin 900ms linear infinite;
1897
+ }
1898
+
1899
+ @keyframes page-in {
1900
+ from {
1901
+ opacity: 0;
1902
+ transform: translateY(12px);
1903
+ }
1904
+ }
1905
+
1906
+ @keyframes spin {
1907
+ to {
1908
+ transform: rotate(360deg);
1909
+ }
1910
+ }
1911
+
1912
+ @media (max-width: 720px) {
1913
+ .feedback-submit {
1914
+ grid-template-columns: 1fr;
1915
+ gap: 1.5rem;
1916
+ padding: 1.25rem;
1917
+ }
1918
+
1919
+ .feedback-submit[data-display="overlay"] {
1920
+ grid-template-columns: minmax(0, 1fr);
1921
+ }
1922
+
1923
+ .feedback-submit-form input,
1924
+ .feedback-submit-form textarea,
1925
+ .feedback-submit-form select {
1926
+ font-size: 1rem;
1927
+ }
1928
+
1929
+ .feedback-post-type-picker {
1930
+ grid-template-columns: 1fr;
1931
+ }
1932
+
1933
+ .feedback-post-type-card {
1934
+ min-height: auto;
1935
+ grid-template-columns: auto 1fr auto;
1936
+ grid-template-rows: 1fr;
1937
+ gap: 0.875rem;
1938
+ align-items: center;
1939
+ }
1940
+
1941
+ .feedback-post-type-card > svg {
1942
+ grid-column: 1;
1943
+ grid-row: 1;
1944
+ }
1945
+
1946
+ .feedback-post-type-copy {
1947
+ grid-column: 2;
1948
+ grid-row: 1;
1949
+ }
1950
+
1951
+ .feedback-post-type-card > [data-slot="radio-group-item"] {
1952
+ grid-column: 3;
1953
+ grid-row: 1;
1954
+ }
1955
+
1956
+ .feedback-submit-actions {
1957
+ display: grid;
1958
+ }
1959
+ }
1960
+
1961
+ @media (max-width: 640px) {
1962
+ .portal-header {
1963
+ padding-inline: 1rem;
1964
+ }
1965
+
1966
+ .portal-header nav {
1967
+ gap: 0.75rem;
1968
+ }
1969
+
1970
+ .portal-header nav a {
1971
+ font-size: 0.66rem;
1972
+ }
1973
+
1974
+ .feedback-index {
1975
+ width: auto;
1976
+ padding: 3.5rem 1rem 4rem;
1977
+ }
1978
+
1979
+ .feedback-detail {
1980
+ width: auto;
1981
+ padding: 2.5rem 1rem 4rem;
1982
+ }
1983
+
1984
+ .public-error {
1985
+ width: auto;
1986
+ padding: 3rem 1rem;
1987
+ }
1988
+
1989
+ .public-error-actions {
1990
+ display: grid;
1991
+ width: 100%;
1992
+ }
1993
+
1994
+ .public-error-actions button,
1995
+ .public-error-actions a {
1996
+ justify-content: center;
1997
+ }
1998
+
1999
+ .roadmap-page {
2000
+ width: auto;
2001
+ padding: 3.5rem 1rem 4rem;
2002
+ }
2003
+
2004
+ .roadmap-intro,
2005
+ .roadmap-intro {
2006
+ grid-template-columns: 1fr;
2007
+ }
2008
+
2009
+ .roadmap-intro .feedback-eyebrow {
2010
+ grid-column: auto;
2011
+ margin-bottom: -0.5rem;
2012
+ }
2013
+
2014
+ .roadmap-groups {
2015
+ grid-template-columns: repeat(3, minmax(82vw, 1fr));
2016
+ gap: 1px;
2017
+ margin-top: 4rem;
2018
+ overflow-x: auto;
2019
+ scroll-snap-type: x mandatory;
2020
+ overscroll-behavior-inline: contain;
2021
+ scrollbar-width: thin;
2022
+ }
2023
+
2024
+ .roadmap-group {
2025
+ scroll-snap-align: start;
2026
+ scroll-snap-stop: always;
2027
+ }
2028
+
2029
+ .feedback-detail article {
2030
+ margin-top: 4rem;
2031
+ }
2032
+
2033
+ .feedback-detail h1 {
2034
+ font-size: clamp(3rem, 15vw, 4.25rem);
2035
+ }
2036
+
2037
+ .feedback-detail-dates {
2038
+ flex-direction: column;
2039
+ gap: 1.25rem;
2040
+ }
2041
+
2042
+ .feedback-intro h1 {
2043
+ font-size: clamp(2rem, 10vw, 3rem);
2044
+ }
2045
+
2046
+ .feedback-filters {
2047
+ grid-template-columns: 1fr;
2048
+ }
2049
+
2050
+ .feedback-filters select,
2051
+ .feedback-filters button {
2052
+ min-height: 3rem;
2053
+ }
2054
+
2055
+ .feedback-list article > p {
2056
+ display: -webkit-box;
2057
+ overflow: hidden;
2058
+ -webkit-box-orient: vertical;
2059
+ -webkit-line-clamp: 3;
2060
+ }
2061
+ }
2062
+
2063
+ @media (max-width: 880px) {
2064
+ .public-post-detail .post-detail-layout {
2065
+ grid-template-columns: 1fr;
2066
+ }
2067
+
2068
+ .post-detail-sidebar {
2069
+ border-top: 1px solid var(--portal-rule);
2070
+ border-left: 0;
2071
+ }
2072
+ }
2073
+
2074
+ @media (max-width: 640px) {
2075
+ .public-post-detail {
2076
+ width: auto;
2077
+ }
2078
+
2079
+ .public-post-detail .post-detail-layout {
2080
+ margin-top: 1rem;
2081
+ }
2082
+
2083
+ .public-post-detail[data-display="overlay"] .post-detail-layout {
2084
+ margin-top: 0;
2085
+ }
2086
+
2087
+ .public-post-detail h1 {
2088
+ font-size: clamp(1.85rem, 8vw, 2.5rem);
2089
+ }
2090
+
2091
+ .post-detail-primary,
2092
+ .post-detail-sidebar {
2093
+ padding: 1.25rem;
2094
+ }
2095
+
2096
+ .post-detail-engagement {
2097
+ align-items: stretch;
2098
+ }
2099
+
2100
+ .post-detail-engagement > span:last-child {
2101
+ justify-content: flex-end;
2102
+ }
2103
+
2104
+ .post-detail-comments-empty {
2105
+ min-height: 10rem;
2106
+ }
2107
+
2108
+ .comment[data-reply="true"] {
2109
+ margin-left: 0.75rem;
2110
+ padding-left: 0.75rem;
2111
+ }
2112
+
2113
+ .comment-header {
2114
+ align-items: flex-start;
2115
+ flex-direction: column;
2116
+ gap: 0.35rem;
2117
+ }
2118
+
2119
+ .post-detail-details > div {
2120
+ grid-template-columns: minmax(5rem, 0.65fr) minmax(0, 1fr);
2121
+ }
2122
+
2123
+ .post-full-page-link {
2124
+ min-height: 3.75rem;
2125
+ padding-right: 1.25rem;
2126
+ }
2127
+ }
2128
+
2129
+ @media (prefers-reduced-motion: reduce) {
2130
+ *,
2131
+ *::before,
2132
+ *::after {
2133
+ scroll-behavior: auto !important;
2134
+ animation-duration: 0.01ms !important;
2135
+ animation-iteration-count: 1 !important;
2136
+ transition-duration: 0.01ms !important;
2137
+ }
2138
+ }