@geekity/cms 0.3.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 (238) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +870 -0
  3. package/admin/layouts/_flash.njk +5 -0
  4. package/admin/layouts/base.njk +27 -0
  5. package/admin/layouts/dashboard.njk +78 -0
  6. package/admin/layouts/document-conflict.njk +49 -0
  7. package/admin/layouts/document-editor.njk +167 -0
  8. package/admin/layouts/document-list.njk +92 -0
  9. package/admin/layouts/federation.njk +145 -0
  10. package/admin/layouts/login.njk +23 -0
  11. package/admin/layouts/placeholder.njk +10 -0
  12. package/admin/layouts/settings.njk +116 -0
  13. package/admin/layouts/setup.njk +27 -0
  14. package/admin/layouts/shell.njk +37 -0
  15. package/admin/layouts/users.njk +91 -0
  16. package/admin/static/admin.css +726 -0
  17. package/admin/static/editor.js +30 -0
  18. package/dist/admin/assets.d.ts +26 -0
  19. package/dist/admin/assets.d.ts.map +1 -0
  20. package/dist/admin/assets.js +38 -0
  21. package/dist/admin/assets.js.map +1 -0
  22. package/dist/admin/credentials.d.ts +28 -0
  23. package/dist/admin/credentials.d.ts.map +1 -0
  24. package/dist/admin/credentials.js +39 -0
  25. package/dist/admin/credentials.js.map +1 -0
  26. package/dist/admin/documents.d.ts +134 -0
  27. package/dist/admin/documents.d.ts.map +1 -0
  28. package/dist/admin/documents.js +613 -0
  29. package/dist/admin/documents.js.map +1 -0
  30. package/dist/admin/federation.d.ts +194 -0
  31. package/dist/admin/federation.d.ts.map +1 -0
  32. package/dist/admin/federation.js +299 -0
  33. package/dist/admin/federation.js.map +1 -0
  34. package/dist/admin/flash.d.ts +24 -0
  35. package/dist/admin/flash.d.ts.map +1 -0
  36. package/dist/admin/flash.js +31 -0
  37. package/dist/admin/flash.js.map +1 -0
  38. package/dist/admin/index.d.ts +23 -0
  39. package/dist/admin/index.d.ts.map +1 -0
  40. package/dist/admin/index.js +15 -0
  41. package/dist/admin/index.js.map +1 -0
  42. package/dist/admin/passwords.d.ts +49 -0
  43. package/dist/admin/passwords.d.ts.map +1 -0
  44. package/dist/admin/passwords.js +122 -0
  45. package/dist/admin/passwords.js.map +1 -0
  46. package/dist/admin/preview.d.ts +18 -0
  47. package/dist/admin/preview.d.ts.map +1 -0
  48. package/dist/admin/preview.js +83 -0
  49. package/dist/admin/preview.js.map +1 -0
  50. package/dist/admin/routes.d.ts +54 -0
  51. package/dist/admin/routes.d.ts.map +1 -0
  52. package/dist/admin/routes.js +383 -0
  53. package/dist/admin/routes.js.map +1 -0
  54. package/dist/admin/session.d.ts +44 -0
  55. package/dist/admin/session.d.ts.map +1 -0
  56. package/dist/admin/session.js +69 -0
  57. package/dist/admin/session.js.map +1 -0
  58. package/dist/admin/settings.d.ts +194 -0
  59. package/dist/admin/settings.d.ts.map +1 -0
  60. package/dist/admin/settings.js +470 -0
  61. package/dist/admin/settings.js.map +1 -0
  62. package/dist/admin/store.d.ts +407 -0
  63. package/dist/admin/store.d.ts.map +1 -0
  64. package/dist/admin/store.js +704 -0
  65. package/dist/admin/store.js.map +1 -0
  66. package/dist/admin/templates.d.ts +36 -0
  67. package/dist/admin/templates.d.ts.map +1 -0
  68. package/dist/admin/templates.js +43 -0
  69. package/dist/admin/templates.js.map +1 -0
  70. package/dist/admin/uploads.d.ts +96 -0
  71. package/dist/admin/uploads.d.ts.map +1 -0
  72. package/dist/admin/uploads.js +179 -0
  73. package/dist/admin/uploads.js.map +1 -0
  74. package/dist/admin/users.d.ts +95 -0
  75. package/dist/admin/users.d.ts.map +1 -0
  76. package/dist/admin/users.js +233 -0
  77. package/dist/admin/users.js.map +1 -0
  78. package/dist/cli.d.ts +85 -0
  79. package/dist/cli.d.ts.map +1 -0
  80. package/dist/cli.js +424 -0
  81. package/dist/cli.js.map +1 -0
  82. package/dist/config.d.ts +172 -0
  83. package/dist/config.d.ts.map +1 -0
  84. package/dist/config.js +184 -0
  85. package/dist/config.js.map +1 -0
  86. package/dist/content/document.d.ts +66 -0
  87. package/dist/content/document.d.ts.map +1 -0
  88. package/dist/content/document.js +13 -0
  89. package/dist/content/document.js.map +1 -0
  90. package/dist/content/index.d.ts +17 -0
  91. package/dist/content/index.d.ts.map +1 -0
  92. package/dist/content/index.js +10 -0
  93. package/dist/content/index.js.map +1 -0
  94. package/dist/content/markdown.d.ts +3 -0
  95. package/dist/content/markdown.d.ts.map +1 -0
  96. package/dist/content/markdown.js +39 -0
  97. package/dist/content/markdown.js.map +1 -0
  98. package/dist/content/media.d.ts +65 -0
  99. package/dist/content/media.d.ts.map +1 -0
  100. package/dist/content/media.js +143 -0
  101. package/dist/content/media.js.map +1 -0
  102. package/dist/content/parser.d.ts +24 -0
  103. package/dist/content/parser.d.ts.map +1 -0
  104. package/dist/content/parser.js +165 -0
  105. package/dist/content/parser.js.map +1 -0
  106. package/dist/content/save.d.ts +60 -0
  107. package/dist/content/save.d.ts.map +1 -0
  108. package/dist/content/save.js +103 -0
  109. package/dist/content/save.js.map +1 -0
  110. package/dist/content/slug.d.ts +25 -0
  111. package/dist/content/slug.d.ts.map +1 -0
  112. package/dist/content/slug.js +75 -0
  113. package/dist/content/slug.js.map +1 -0
  114. package/dist/content/store.d.ts +133 -0
  115. package/dist/content/store.d.ts.map +1 -0
  116. package/dist/content/store.js +411 -0
  117. package/dist/content/store.js.map +1 -0
  118. package/dist/content/sync.d.ts +146 -0
  119. package/dist/content/sync.d.ts.map +1 -0
  120. package/dist/content/sync.js +421 -0
  121. package/dist/content/sync.js.map +1 -0
  122. package/dist/content/writer.d.ts +37 -0
  123. package/dist/content/writer.d.ts.map +1 -0
  124. package/dist/content/writer.js +97 -0
  125. package/dist/content/writer.js.map +1 -0
  126. package/dist/env.d.ts +48 -0
  127. package/dist/env.d.ts.map +1 -0
  128. package/dist/env.js +2 -0
  129. package/dist/env.js.map +1 -0
  130. package/dist/federation/actor.d.ts +55 -0
  131. package/dist/federation/actor.d.ts.map +1 -0
  132. package/dist/federation/actor.js +101 -0
  133. package/dist/federation/actor.js.map +1 -0
  134. package/dist/federation/article.d.ts +83 -0
  135. package/dist/federation/article.d.ts.map +1 -0
  136. package/dist/federation/article.js +169 -0
  137. package/dist/federation/article.js.map +1 -0
  138. package/dist/federation/delivery.d.ts +90 -0
  139. package/dist/federation/delivery.d.ts.map +1 -0
  140. package/dist/federation/delivery.js +289 -0
  141. package/dist/federation/delivery.js.map +1 -0
  142. package/dist/federation/federation.d.ts +75 -0
  143. package/dist/federation/federation.d.ts.map +1 -0
  144. package/dist/federation/federation.js +190 -0
  145. package/dist/federation/federation.js.map +1 -0
  146. package/dist/federation/followers.d.ts +43 -0
  147. package/dist/federation/followers.d.ts.map +1 -0
  148. package/dist/federation/followers.js +69 -0
  149. package/dist/federation/followers.js.map +1 -0
  150. package/dist/federation/inbox.d.ts +68 -0
  151. package/dist/federation/inbox.d.ts.map +1 -0
  152. package/dist/federation/inbox.js +171 -0
  153. package/dist/federation/inbox.js.map +1 -0
  154. package/dist/federation/index.d.ts +14 -0
  155. package/dist/federation/index.d.ts.map +1 -0
  156. package/dist/federation/index.js +10 -0
  157. package/dist/federation/index.js.map +1 -0
  158. package/dist/federation/keys.d.ts +27 -0
  159. package/dist/federation/keys.d.ts.map +1 -0
  160. package/dist/federation/keys.js +60 -0
  161. package/dist/federation/keys.js.map +1 -0
  162. package/dist/federation/mount.d.ts +23 -0
  163. package/dist/federation/mount.d.ts.map +1 -0
  164. package/dist/federation/mount.js +71 -0
  165. package/dist/federation/mount.js.map +1 -0
  166. package/dist/federation/paths.d.ts +85 -0
  167. package/dist/federation/paths.d.ts.map +1 -0
  168. package/dist/federation/paths.js +97 -0
  169. package/dist/federation/paths.js.map +1 -0
  170. package/dist/index.d.ts +106 -0
  171. package/dist/index.d.ts.map +1 -0
  172. package/dist/index.js +148 -0
  173. package/dist/index.js.map +1 -0
  174. package/dist/init.d.ts +71 -0
  175. package/dist/init.d.ts.map +1 -0
  176. package/dist/init.js +125 -0
  177. package/dist/init.js.map +1 -0
  178. package/dist/web/assets.d.ts +65 -0
  179. package/dist/web/assets.d.ts.map +1 -0
  180. package/dist/web/assets.js +152 -0
  181. package/dist/web/assets.js.map +1 -0
  182. package/dist/web/context.d.ts +121 -0
  183. package/dist/web/context.d.ts.map +1 -0
  184. package/dist/web/context.js +112 -0
  185. package/dist/web/context.js.map +1 -0
  186. package/dist/web/documents.d.ts +28 -0
  187. package/dist/web/documents.d.ts.map +1 -0
  188. package/dist/web/documents.js +39 -0
  189. package/dist/web/documents.js.map +1 -0
  190. package/dist/web/feeds.d.ts +122 -0
  191. package/dist/web/feeds.d.ts.map +1 -0
  192. package/dist/web/feeds.js +229 -0
  193. package/dist/web/feeds.js.map +1 -0
  194. package/dist/web/index.d.ts +17 -0
  195. package/dist/web/index.d.ts.map +1 -0
  196. package/dist/web/index.js +10 -0
  197. package/dist/web/index.js.map +1 -0
  198. package/dist/web/negotiate.d.ts +219 -0
  199. package/dist/web/negotiate.d.ts.map +1 -0
  200. package/dist/web/negotiate.js +409 -0
  201. package/dist/web/negotiate.js.map +1 -0
  202. package/dist/web/pagination.d.ts +48 -0
  203. package/dist/web/pagination.d.ts.map +1 -0
  204. package/dist/web/pagination.js +30 -0
  205. package/dist/web/pagination.js.map +1 -0
  206. package/dist/web/render.d.ts +72 -0
  207. package/dist/web/render.d.ts.map +1 -0
  208. package/dist/web/render.js +73 -0
  209. package/dist/web/render.js.map +1 -0
  210. package/dist/web/routes.d.ts +31 -0
  211. package/dist/web/routes.d.ts.map +1 -0
  212. package/dist/web/routes.js +366 -0
  213. package/dist/web/routes.js.map +1 -0
  214. package/dist/web/templates.d.ts +34 -0
  215. package/dist/web/templates.d.ts.map +1 -0
  216. package/dist/web/templates.js +106 -0
  217. package/dist/web/templates.js.map +1 -0
  218. package/package.json +68 -0
  219. package/templates/site/content/_data/site.json +8 -0
  220. package/templates/site/content/pages/about.md +11 -0
  221. package/templates/site/content/pages/pages.json +3 -0
  222. package/templates/site/content/posts/2026-01-01-hello-world.md +34 -0
  223. package/templates/site/content/posts/posts.json +4 -0
  224. package/templates/site/geekity.config.ts +11 -0
  225. package/templates/site/gitignore +3 -0
  226. package/templates/site/server.ts +20 -0
  227. package/templates/site/tsconfig.json +18 -0
  228. package/themes/default/README.md +148 -0
  229. package/themes/default/layouts/404.njk +9 -0
  230. package/themes/default/layouts/base.njk +59 -0
  231. package/themes/default/layouts/home.njk +9 -0
  232. package/themes/default/layouts/page.njk +13 -0
  233. package/themes/default/layouts/post.njk +30 -0
  234. package/themes/default/layouts/tag.njk +19 -0
  235. package/themes/default/partials/pagination.njk +14 -0
  236. package/themes/default/partials/post-list.njk +24 -0
  237. package/themes/default/partials/tags.njk +12 -0
  238. package/themes/default/static/style.css +327 -0
@@ -0,0 +1,726 @@
1
+ /*
2
+ * The admin's stylesheet. Plain CSS, no build step, no CDN: the admin is
3
+ * server-rendered HTML and this is the only thing it loads.
4
+ *
5
+ * The shape is WordPress classic — a dark bar across the top, a dark column of
6
+ * navigation down the left, content on a grey field — because that is the
7
+ * layout the people this CMS is for already know how to read.
8
+ */
9
+
10
+ :root {
11
+ --admin-bar: #1d2327;
12
+ --admin-nav: #2c3338;
13
+ --admin-nav-text: #f0f0f1;
14
+ --admin-nav-current: #2271b1;
15
+ --admin-field: #f0f0f1;
16
+ --admin-surface: #fff;
17
+ --admin-border: #c3c4c7;
18
+ --admin-text: #1d2327;
19
+ --admin-muted: #646970;
20
+ --admin-link: #2271b1;
21
+ --admin-notice: #00a32a;
22
+ --admin-error: #d63638;
23
+ --admin-nav-width: 11rem;
24
+ }
25
+
26
+ * {
27
+ box-sizing: border-box;
28
+ }
29
+
30
+ body {
31
+ margin: 0;
32
+ background: var(--admin-field);
33
+ color: var(--admin-text);
34
+ font:
35
+ 14px/1.6 -apple-system,
36
+ BlinkMacSystemFont,
37
+ 'Segoe UI',
38
+ Roboto,
39
+ sans-serif;
40
+ }
41
+
42
+ a {
43
+ color: var(--admin-link);
44
+ }
45
+
46
+ /* The top bar: site name on the left, who you are on the right. */
47
+
48
+ .admin-bar {
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 1rem;
52
+ padding: 0 1rem;
53
+ min-height: 2.5rem;
54
+ background: var(--admin-bar);
55
+ color: var(--admin-nav-text);
56
+ }
57
+
58
+ .admin-bar a {
59
+ color: var(--admin-nav-text);
60
+ text-decoration: none;
61
+ }
62
+
63
+ .admin-bar a:hover,
64
+ .admin-bar a:focus {
65
+ color: #72aee6;
66
+ }
67
+
68
+ .admin-bar-site {
69
+ font-weight: 600;
70
+ }
71
+
72
+ .admin-bar-spacer {
73
+ flex: 1;
74
+ }
75
+
76
+ .admin-bar-user {
77
+ color: #c3c4c7;
78
+ }
79
+
80
+ .admin-bar form {
81
+ display: inline;
82
+ }
83
+
84
+ .admin-bar button {
85
+ padding: 0;
86
+ border: 0;
87
+ background: none;
88
+ color: var(--admin-nav-text);
89
+ font: inherit;
90
+ cursor: pointer;
91
+ text-decoration: underline;
92
+ }
93
+
94
+ /* The shell: navigation column beside the screen itself. */
95
+
96
+ .admin-shell {
97
+ display: flex;
98
+ align-items: stretch;
99
+ min-height: calc(100vh - 2.5rem);
100
+ }
101
+
102
+ .admin-nav {
103
+ flex: 0 0 var(--admin-nav-width);
104
+ background: var(--admin-nav);
105
+ }
106
+
107
+ .admin-nav ul {
108
+ margin: 0;
109
+ padding: 0;
110
+ list-style: none;
111
+ }
112
+
113
+ .admin-nav a {
114
+ display: block;
115
+ padding: 0.6rem 0.9rem;
116
+ color: var(--admin-nav-text);
117
+ text-decoration: none;
118
+ }
119
+
120
+ .admin-nav a:hover,
121
+ .admin-nav a:focus {
122
+ background: var(--admin-bar);
123
+ color: #72aee6;
124
+ }
125
+
126
+ .admin-nav a[aria-current='page'] {
127
+ background: var(--admin-nav-current);
128
+ color: #fff;
129
+ font-weight: 600;
130
+ }
131
+
132
+ .admin-main {
133
+ flex: 1;
134
+ min-width: 0;
135
+ padding: 1.25rem 1.5rem 3rem;
136
+ }
137
+
138
+ /* Login and setup: no navigation, one card in the middle of the page. */
139
+
140
+ .admin-plain {
141
+ max-width: 22rem;
142
+ margin: 3rem auto;
143
+ padding: 1.5rem;
144
+ background: var(--admin-surface);
145
+ border: 1px solid var(--admin-border);
146
+ }
147
+
148
+ h1 {
149
+ margin-top: 0;
150
+ font-size: 1.5rem;
151
+ font-weight: 400;
152
+ }
153
+
154
+ h2 {
155
+ margin-top: 0;
156
+ font-size: 1.05rem;
157
+ }
158
+
159
+ /* Flash messages. One page each, then gone. */
160
+
161
+ .admin-flash {
162
+ margin: 0 0 1rem;
163
+ padding: 0.6rem 0.9rem;
164
+ background: var(--admin-surface);
165
+ border: 1px solid var(--admin-border);
166
+ border-left: 4px solid var(--admin-notice);
167
+ }
168
+
169
+ .admin-flash-error {
170
+ border-left-color: var(--admin-error);
171
+ }
172
+
173
+ /* Panels, the box every group of things on the dashboard sits in. */
174
+
175
+ .admin-panels {
176
+ display: grid;
177
+ gap: 1rem;
178
+ grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
179
+ align-items: start;
180
+ }
181
+
182
+ .admin-panel {
183
+ padding: 0.9rem 1.1rem 1.1rem;
184
+ background: var(--admin-surface);
185
+ border: 1px solid var(--admin-border);
186
+ }
187
+
188
+ .admin-counts {
189
+ display: flex;
190
+ margin: 0;
191
+ gap: 1.5rem;
192
+ }
193
+
194
+ .admin-counts div {
195
+ display: flex;
196
+ flex-direction: column-reverse;
197
+ }
198
+
199
+ .admin-counts dt {
200
+ color: var(--admin-muted);
201
+ }
202
+
203
+ .admin-counts dd {
204
+ margin: 0;
205
+ font-size: 1.75rem;
206
+ line-height: 1.2;
207
+ }
208
+
209
+ /* Listings. */
210
+
211
+ .admin-list {
212
+ width: 100%;
213
+ border-collapse: collapse;
214
+ }
215
+
216
+ .admin-list th {
217
+ text-align: left;
218
+ color: var(--admin-muted);
219
+ font-weight: 600;
220
+ }
221
+
222
+ .admin-list th,
223
+ .admin-list td {
224
+ padding: 0.35rem 0.5rem 0.35rem 0;
225
+ border-bottom: 1px solid var(--admin-field);
226
+ vertical-align: top;
227
+ }
228
+
229
+ .admin-status {
230
+ color: var(--admin-muted);
231
+ }
232
+
233
+ .admin-status-draft {
234
+ color: var(--admin-error);
235
+ }
236
+
237
+ .admin-empty {
238
+ color: var(--admin-muted);
239
+ }
240
+
241
+ /* Forms. */
242
+
243
+ label {
244
+ display: block;
245
+ margin: 0.75rem 0 0.25rem;
246
+ font-weight: 600;
247
+ }
248
+
249
+ input[type='text'],
250
+ input[type='password'],
251
+ textarea {
252
+ width: 100%;
253
+ padding: 0.4rem 0.5rem;
254
+ border: 1px solid #8c8f94;
255
+ background: var(--admin-surface);
256
+ color: inherit;
257
+ font: inherit;
258
+ }
259
+
260
+ textarea {
261
+ min-height: 8rem;
262
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
263
+ resize: vertical;
264
+ }
265
+
266
+ button[type='submit'],
267
+ .admin-button {
268
+ margin-top: 1rem;
269
+ padding: 0.4rem 0.9rem;
270
+ border: 1px solid var(--admin-link);
271
+ border-radius: 3px;
272
+ background: var(--admin-link);
273
+ color: #fff;
274
+ font: inherit;
275
+ cursor: pointer;
276
+ }
277
+
278
+ button[type='submit']:hover,
279
+ .admin-button:hover {
280
+ background: #135e96;
281
+ }
282
+
283
+ .admin-error {
284
+ margin: 1rem 0 0;
285
+ padding: 0.6rem 0.9rem;
286
+ background: var(--admin-surface);
287
+ border-left: 4px solid var(--admin-error);
288
+ }
289
+
290
+ .admin-note {
291
+ color: var(--admin-muted);
292
+ }
293
+
294
+ /* The listing's filter links: all / published / drafts / trash. */
295
+
296
+ .admin-filters {
297
+ display: flex;
298
+ gap: 0.75rem;
299
+ margin: 0 0 0.75rem;
300
+ padding: 0;
301
+ list-style: none;
302
+ }
303
+
304
+ .admin-filters a[aria-current] {
305
+ color: var(--admin-text);
306
+ font-weight: 600;
307
+ text-decoration: none;
308
+ }
309
+
310
+ /* The row actions. They are links and one small form, and read as one line. */
311
+
312
+ .admin-actions {
313
+ display: flex;
314
+ align-items: baseline;
315
+ gap: 0.6rem;
316
+ white-space: nowrap;
317
+ }
318
+
319
+ .admin-actions form {
320
+ display: inline;
321
+ }
322
+
323
+ .admin-actions button {
324
+ margin: 0;
325
+ padding: 0;
326
+ border: 0;
327
+ background: none;
328
+ color: var(--admin-link);
329
+ font: inherit;
330
+ cursor: pointer;
331
+ text-decoration: underline;
332
+ }
333
+
334
+ .admin-status-trashed {
335
+ color: var(--admin-muted);
336
+ font-style: italic;
337
+ }
338
+
339
+ .admin-pagination {
340
+ display: flex;
341
+ gap: 0.75rem;
342
+ margin-top: 1rem;
343
+ color: var(--admin-muted);
344
+ }
345
+
346
+ /* The editor: the writing on the left, everything about it on the right. */
347
+
348
+ .admin-editor {
349
+ display: grid;
350
+ gap: 1rem;
351
+ grid-template-columns: minmax(0, 3fr) minmax(15rem, 1fr);
352
+ align-items: start;
353
+ }
354
+
355
+ @media (max-width: 60rem) {
356
+ .admin-editor {
357
+ grid-template-columns: minmax(0, 1fr);
358
+ }
359
+ }
360
+
361
+ .admin-editor-main,
362
+ .admin-editor-side {
363
+ padding: 0.9rem 1.1rem 1.1rem;
364
+ background: var(--admin-surface);
365
+ border: 1px solid var(--admin-border);
366
+ }
367
+
368
+ .admin-editor-main label:first-child,
369
+ .admin-editor-side label:first-child {
370
+ margin-top: 0;
371
+ }
372
+
373
+ .admin-editor-main textarea {
374
+ min-height: 28rem;
375
+ }
376
+
377
+ .admin-hint {
378
+ margin: 0.25rem 0 0;
379
+ color: var(--admin-muted);
380
+ font-size: 0.9em;
381
+ }
382
+
383
+ .admin-check {
384
+ display: flex;
385
+ align-items: center;
386
+ gap: 0.4rem;
387
+ margin: 1rem 0 0;
388
+ }
389
+
390
+ .admin-check label {
391
+ margin: 0;
392
+ font-weight: 400;
393
+ }
394
+
395
+ .admin-check input {
396
+ width: auto;
397
+ }
398
+
399
+ .admin-editor-buttons {
400
+ display: flex;
401
+ flex-wrap: wrap;
402
+ align-items: center;
403
+ gap: 0.5rem;
404
+ margin: 0;
405
+ }
406
+
407
+ /* A link that has to look like a button: Add new, View. */
408
+
409
+ .admin-button {
410
+ display: inline-block;
411
+ text-decoration: none;
412
+ }
413
+
414
+ .admin-button-small {
415
+ margin: 0 0 0 0.5rem;
416
+ padding: 0.15rem 0.5rem;
417
+ font-size: 0.8rem;
418
+ vertical-align: middle;
419
+ }
420
+
421
+ .admin-button-quiet {
422
+ background: var(--admin-surface);
423
+ color: var(--admin-link);
424
+ }
425
+
426
+ .admin-button-quiet:hover {
427
+ background: var(--admin-field);
428
+ }
429
+
430
+ /* The conflict screen: the two versions, side by side, both readable. */
431
+
432
+ .admin-conflict {
433
+ display: grid;
434
+ gap: 1rem;
435
+ grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
436
+ }
437
+
438
+ .admin-conflict section {
439
+ padding: 0.9rem 1.1rem 1.1rem;
440
+ background: var(--admin-surface);
441
+ border: 1px solid var(--admin-border);
442
+ }
443
+
444
+ .admin-conflict textarea {
445
+ min-height: 20rem;
446
+ }
447
+
448
+ .admin-conflict-actions {
449
+ margin: 1rem 0 0;
450
+ }
451
+
452
+ /* A field the page carries but nobody should have to look at. */
453
+
454
+ .admin-hidden-field {
455
+ position: absolute;
456
+ width: 1px;
457
+ height: 1px;
458
+ padding: 0;
459
+ border: 0;
460
+ overflow: hidden;
461
+ clip-path: inset(50%);
462
+ }
463
+
464
+ /* The editor's enhancement: the Write/Preview tabs, the CodeMirror surface,
465
+ the preview frame and the upload control. Every rule here is inert until
466
+ editor.js has run — with JavaScript off, `.admin-editor-tools` holds one
467
+ Preview button and nothing else. */
468
+
469
+ .admin-editor-tools {
470
+ display: flex;
471
+ flex-wrap: wrap;
472
+ align-items: center;
473
+ gap: 0.5rem;
474
+ margin-top: 0.75rem;
475
+ }
476
+
477
+ .admin-editor-tabs {
478
+ display: flex;
479
+ gap: 0.25rem;
480
+ margin-right: auto;
481
+ }
482
+
483
+ .admin-editor-tab {
484
+ margin: 0;
485
+ padding: 0.3rem 0.8rem;
486
+ border: 1px solid var(--admin-border);
487
+ border-radius: 3px;
488
+ background: var(--admin-field);
489
+ color: var(--admin-text);
490
+ font: inherit;
491
+ cursor: pointer;
492
+ }
493
+
494
+ .admin-editor-tab[aria-selected='true'] {
495
+ background: var(--admin-surface);
496
+ border-color: var(--admin-link);
497
+ color: var(--admin-link);
498
+ font-weight: 600;
499
+ }
500
+
501
+ /* The stylesheet gives `button[type='submit']` its shape, and this one is a
502
+ `type="button"`, so it has to be given the same shape by hand. */
503
+
504
+ .admin-editor-upload button {
505
+ margin: 0;
506
+ padding: 0.3rem 0.8rem;
507
+ border: 1px solid var(--admin-border);
508
+ border-radius: 3px;
509
+ background: var(--admin-surface);
510
+ color: var(--admin-link);
511
+ font: inherit;
512
+ cursor: pointer;
513
+ }
514
+
515
+ .admin-editor-upload button:hover {
516
+ background: var(--admin-field);
517
+ }
518
+
519
+ .admin-editor-status {
520
+ flex: 1 0 100%;
521
+ margin: 0;
522
+ min-height: 1.2em;
523
+ color: var(--admin-muted);
524
+ font-size: 0.9em;
525
+ }
526
+
527
+ /* CodeMirror sits where the textarea was, and is the same height it was. */
528
+
529
+ .admin-editor-surface .cm-editor {
530
+ height: 28rem;
531
+ border: 1px solid var(--admin-border);
532
+ border-radius: 3px;
533
+ font-size: 0.95rem;
534
+ }
535
+
536
+ .admin-editor-surface .cm-editor.cm-focused {
537
+ outline: 2px solid var(--admin-link);
538
+ outline-offset: -1px;
539
+ }
540
+
541
+ .admin-editor-surface .cm-scroller {
542
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
543
+ line-height: 1.5;
544
+ }
545
+
546
+ /* The preview is the site's own page, so it is framed rather than inlined:
547
+ the theme's stylesheet has no business in the admin's. */
548
+
549
+ .admin-editor-preview {
550
+ width: 100%;
551
+ height: 28rem;
552
+ border: 1px solid var(--admin-border);
553
+ border-radius: 3px;
554
+ background: #fff;
555
+ }
556
+
557
+ /* The settings screen: one column of fields, narrow enough to read across. */
558
+
559
+ .admin-settings {
560
+ max-width: 42rem;
561
+ padding: 0.9rem 1.1rem 1.1rem;
562
+ background: var(--admin-surface);
563
+ border: 1px solid var(--admin-border);
564
+ }
565
+
566
+ .admin-settings h2 {
567
+ margin: 1.75rem 0 0;
568
+ padding-top: 1rem;
569
+ border-top: 1px solid var(--admin-border);
570
+ font-size: 1.05rem;
571
+ }
572
+
573
+ .admin-settings h2:first-child {
574
+ margin-top: 0;
575
+ padding-top: 0;
576
+ border-top: 0;
577
+ }
578
+
579
+ .admin-settings select {
580
+ padding: 0.4rem 0.5rem;
581
+ border: 1px solid #8c8f94;
582
+ background: var(--admin-surface);
583
+ color: inherit;
584
+ font: inherit;
585
+ }
586
+
587
+ .admin-settings input:disabled {
588
+ background: var(--admin-field);
589
+ color: var(--admin-muted);
590
+ }
591
+
592
+ /* One message under the field it is about, so it reads with the field
593
+ rather than as a list of complaints at the top of the form. */
594
+
595
+ .admin-field-error {
596
+ margin: 0.25rem 0 0;
597
+ color: var(--admin-error);
598
+ font-size: 0.9em;
599
+ }
600
+
601
+ .admin-settings-buttons {
602
+ margin: 0;
603
+ }
604
+
605
+ /* The users screen stacks the table and two panels of the same shape, so they
606
+ need the gap the settings screen's single panel never did. */
607
+
608
+ .admin-list + .admin-settings,
609
+ .admin-settings + .admin-settings {
610
+ margin-top: 1.5rem;
611
+ }
612
+
613
+ /* The federation screen: the site's own actor, its followers, what arrived,
614
+ and how what went out landed. Four panels down the page rather than the
615
+ dashboard's grid, because three of them hold tables. */
616
+
617
+ .admin-panel + .admin-panel {
618
+ margin-top: 1.5rem;
619
+ }
620
+
621
+ .admin-actor-handle {
622
+ margin: 0 0 0.75rem;
623
+ font-size: 1.25rem;
624
+ font-weight: 600;
625
+ }
626
+
627
+ .admin-actor-fields {
628
+ display: grid;
629
+ margin: 0;
630
+ gap: 0.4rem 1.5rem;
631
+ grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
632
+ }
633
+
634
+ .admin-actor-fields div {
635
+ display: flex;
636
+ gap: 0.5rem;
637
+ }
638
+
639
+ .admin-actor-fields dt {
640
+ min-width: 5.5rem;
641
+ color: var(--admin-muted);
642
+ }
643
+
644
+ .admin-actor-fields dd {
645
+ margin: 0;
646
+ overflow-wrap: anywhere;
647
+ }
648
+
649
+ /* An avatar and a name on one line, with a placeholder square holding the
650
+ space when the actor published no icon: a list of rows that jump between
651
+ two heights is harder to read down than one that does not. */
652
+
653
+ .admin-follower {
654
+ display: flex;
655
+ align-items: center;
656
+ gap: 0.5rem;
657
+ }
658
+
659
+ .admin-avatar {
660
+ flex: none;
661
+ width: 2rem;
662
+ height: 2rem;
663
+ border-radius: 50%;
664
+ object-fit: cover;
665
+ }
666
+
667
+ .admin-avatar-blank {
668
+ display: inline-block;
669
+ background: var(--admin-field);
670
+ }
671
+
672
+ /* The site's own avatar, which is shown big enough to judge on the settings
673
+ screen and beside the actor it belongs to on the federation screen. */
674
+
675
+ .admin-avatar-large {
676
+ width: 6rem;
677
+ height: 6rem;
678
+ border: 1px solid var(--admin-border);
679
+ }
680
+
681
+ .admin-avatar-current {
682
+ display: flex;
683
+ gap: 1rem;
684
+ align-items: flex-start;
685
+ margin-top: 0.75rem;
686
+ }
687
+
688
+ .admin-avatar-forms {
689
+ display: flex;
690
+ flex-wrap: wrap;
691
+ gap: 1rem;
692
+ align-items: flex-end;
693
+ }
694
+
695
+ .admin-avatar-forms label {
696
+ display: block;
697
+ }
698
+
699
+ .admin-actor-identity {
700
+ display: flex;
701
+ gap: 0.75rem;
702
+ align-items: center;
703
+ }
704
+
705
+ .admin-inbox {
706
+ margin: 0;
707
+ padding: 0;
708
+ list-style: none;
709
+ }
710
+
711
+ .admin-inbox li {
712
+ padding: 0.35rem 0;
713
+ border-bottom: 1px solid var(--admin-field);
714
+ }
715
+
716
+ .admin-inbox-actor {
717
+ font-weight: 600;
718
+ }
719
+
720
+ .admin-inbox-when {
721
+ color: var(--admin-muted);
722
+ }
723
+
724
+ .admin-status-failed {
725
+ color: var(--admin-error);
726
+ }