A calm place to write long-form, and publish it to the open social web.
skypress.blog/
1---
2import Base from '../layouts/Base.astro';
3import Dashboard from '../components/Dashboard.tsx';
4import LoadingScene from '../components/LoadingScene.astro';
5// Shared top-bar styles (the Dashboard island is client:only, so Astro scoped
6// styles can't reach its DOM). The sign-in form styles are shared with the editor.
7import '../styles/app-bar.css';
8import '../styles/login.css';
9---
10
11<Base title="Dashboard — SkyPress">
12 <main class="dash-shell">
13 <!-- client:only — auth runs only in the browser; its bundle never reaches
14 reading pages (Decisions 0003 & 0004). No `@wordpress/*` here. The
15 fallback shows the durable header + a skeleton until the island loads. -->
16 <Dashboard client:only="react">
17 <LoadingScene slot="fallback" variant="dashboard" />
18 </Dashboard>
19 </main>
20</Base>
21
22<!-- Dashboard is a `client:only` React island, so Astro's scoped styles never reach
23 its DOM. These rules must be global. -->
24<style is:global>
25 .dash__loading,
26 .dash__empty {
27 padding: 1.5rem;
28 color: var(--muted);
29 }
30 .dash__login {
31 max-width: 30rem;
32 margin: 0 auto;
33 padding: 4rem 1.5rem;
34 }
35 .dash__error {
36 color: var(--ember);
37 font-size: 0.9rem;
38 }
39 .dash {
40 max-width: 48rem;
41 margin: 0 auto;
42 padding: 0 1.25rem 5rem;
43 }
44 .dash__bar {
45 padding: 0.9rem 0;
46 }
47 .dash__crumb {
48 border: 0;
49 background: none;
50 font: inherit;
51 font-weight: 600;
52 color: var(--sun);
53 cursor: pointer;
54 padding: 0;
55 }
56 .dash__crumb:disabled {
57 color: var(--muted);
58 cursor: default;
59 }
60 .dash__link {
61 color: var(--sun);
62 text-decoration: none;
63 font-size: 0.9rem;
64 }
65 .dash__link:hover {
66 text-decoration: underline;
67 }
68 .dash__section-head {
69 display: flex;
70 align-items: center;
71 justify-content: space-between;
72 gap: 1rem;
73 flex-wrap: wrap;
74 margin: 1rem 0 1.5rem;
75 }
76 .dash__h1 {
77 font-size: clamp(1.6rem, 4vw, 2.2rem);
78 margin: 0;
79 }
80 .dash__new {
81 border: 0;
82 border-radius: 8px;
83 background: var(--btn-primary);
84 color: #fff;
85 font: inherit;
86 font-weight: 600;
87 padding: 0.5rem 1rem;
88 cursor: pointer;
89 }
90 /* Empty state: creating a publication is the wanted action, so the CTA is
91 prominent here. */
92 .dash__empty-state {
93 display: flex;
94 flex-direction: column;
95 align-items: flex-start;
96 gap: 1rem;
97 padding: 1.5rem;
98 }
99 .dash__empty-state p {
100 margin: 0;
101 color: var(--muted);
102 }
103 /* Once a publication exists, "Write" (in the top bar) is the wanted action, so
104 the add-another button is de-emphasized to a quiet secondary control. */
105 .dash__add {
106 margin-top: 1.5rem;
107 padding-top: 1.25rem;
108 border-top: 1px solid var(--line);
109 }
110 .dash__new-quiet {
111 border: 1px solid var(--line-strong);
112 background: var(--paper-raised);
113 border-radius: 6px;
114 color: var(--ink-soft);
115 font: inherit;
116 font-size: 0.85rem;
117 padding: 0.35rem 0.75rem;
118 cursor: pointer;
119 }
120 .dash__new-quiet:hover {
121 color: var(--ink);
122 }
123 .dash__pubs,
124 .dash__postlist {
125 list-style: none;
126 margin: 0;
127 padding: 0;
128 }
129 .dash__pub {
130 display: flex;
131 align-items: center;
132 gap: 1rem;
133 padding: 0.9rem 0;
134 border-top: 1px solid var(--line);
135 }
136 .dash__publogo {
137 width: 48px;
138 height: 48px;
139 border-radius: 10px;
140 object-fit: cover;
141 flex: none;
142 background: var(--paper-raised);
143 }
144 .dash__publogo--fallback {
145 display: inline-flex;
146 align-items: center;
147 justify-content: center;
148 font-family: var(--font-display);
149 font-weight: 700;
150 color: var(--sun);
151 background: var(--sun-tint);
152 }
153 .dash__pubtext {
154 display: flex;
155 flex-direction: column;
156 flex: 1;
157 min-width: 0;
158 }
159 .dash__pubname {
160 font-weight: 600;
161 font-size: 1.1rem;
162 }
163 .dash__pubslug {
164 color: var(--muted);
165 font-family: var(--font-mono);
166 font-size: 0.78rem;
167 }
168 .dash__foreign {
169 margin-top: 2.5rem;
170 padding-top: 1.5rem;
171 border-top: 1px solid var(--line);
172 }
173 .dash__h2 {
174 font-size: 1.15rem;
175 margin: 0 0 0.25rem;
176 }
177 .dash__foreign-note {
178 color: var(--muted);
179 font-size: 0.9rem;
180 margin: 0 0 0.5rem;
181 }
182 .dash__foreign .dash__pub {
183 opacity: 0.85;
184 }
185 .dash__pubhost {
186 display: inline-flex;
187 align-items: center;
188 gap: 0.3rem;
189 align-self: flex-start;
190 color: var(--muted);
191 font-family: var(--font-mono);
192 font-size: 0.72rem;
193 padding: 0.05rem 0.4rem;
194 border: 1px solid var(--line);
195 border-radius: 999px;
196 background: var(--paper-raised);
197 }
198 .dash__pubhost-logo {
199 flex: none;
200 color: var(--ink-soft);
201 }
202 .dash__pubactions {
203 display: flex;
204 align-items: center;
205 gap: 0.6rem;
206 }
207 .dash__pubactions button,
208 .dash__post button,
209 .dash__post .dash__edit {
210 border: 1px solid var(--line-strong);
211 background: var(--paper-raised);
212 border-radius: 6px;
213 padding: 0.3rem 0.7rem;
214 font: inherit;
215 font-size: 0.85rem;
216 cursor: pointer;
217 }
218 .dash__post .dash__edit {
219 color: inherit;
220 text-decoration: none;
221 display: inline-flex;
222 align-items: center;
223 }
224 .dash__tabs {
225 display: flex;
226 gap: 0.5rem;
227 border-bottom: 1px solid var(--line);
228 margin-bottom: 1.5rem;
229 }
230 .dash__tabs button {
231 border: 0;
232 background: none;
233 font: inherit;
234 padding: 0.5rem 0.25rem;
235 margin-bottom: -1px;
236 border-bottom: 2px solid transparent;
237 color: var(--muted);
238 cursor: pointer;
239 }
240 .dash__tabs button.is-active {
241 color: var(--ink);
242 border-bottom-color: var(--sun);
243 font-weight: 600;
244 }
245 .dash__post {
246 display: flex;
247 align-items: center;
248 gap: 0.85rem;
249 padding: 0.65rem 0;
250 border-top: 1px solid var(--line);
251 }
252 .dash__postlink {
253 flex: 1;
254 min-width: 0;
255 color: var(--ink);
256 text-decoration: none;
257 font-weight: 540;
258 }
259 .dash__postlink:hover {
260 color: var(--sun);
261 }
262 .dash__postdate {
263 color: var(--muted);
264 font-family: var(--font-mono);
265 font-size: 0.72rem;
266 }
267 .dash__danger {
268 border: 1px solid var(--ember);
269 border-radius: var(--radius);
270 padding: 1.25rem;
271 background: color-mix(in srgb, var(--ember) 6%, transparent);
272 }
273 .dash__danger h2 {
274 margin: 0 0 0.5rem;
275 font-size: 1.2rem;
276 }
277 .dash__danger p {
278 color: var(--ink-soft);
279 margin: 0 0 1rem;
280 }
281 .dash__delete {
282 border: 0;
283 border-radius: 8px;
284 background: var(--ember);
285 color: #fff;
286 font: inherit;
287 font-weight: 600;
288 padding: 0.55rem 1rem;
289 cursor: pointer;
290 }
291 .dash__delete:disabled {
292 opacity: 0.6;
293 cursor: not-allowed;
294 }
295
296 /* Publication form */
297 .pubform {
298 max-width: 34rem;
299 }
300 .pubform__title {
301 font-size: 1.4rem;
302 margin: 0 0 1.25rem;
303 }
304 .pubform__logo-row {
305 display: flex;
306 align-items: center;
307 gap: 1rem;
308 margin-bottom: 1.25rem;
309 }
310 .pubform__logo {
311 width: 72px;
312 height: 72px;
313 border-radius: 16px;
314 object-fit: cover;
315 flex: none;
316 background: var(--paper-raised);
317 border: 1px solid var(--line);
318 }
319 .pubform__logo--fallback {
320 display: inline-flex;
321 align-items: center;
322 justify-content: center;
323 font-family: var(--font-display);
324 font-size: 1.8rem;
325 font-weight: 700;
326 color: var(--sun);
327 background: var(--sun-tint);
328 }
329 .pubform__logo-label {
330 display: flex;
331 flex-direction: column;
332 gap: 0.25rem;
333 font-size: 0.85rem;
334 font-weight: 600;
335 }
336 .pubform__logo-label small {
337 font-weight: 400;
338 color: var(--muted);
339 }
340 .pubform__field {
341 display: block;
342 margin-bottom: 1rem;
343 }
344 .pubform__field span {
345 display: block;
346 font-size: 0.85rem;
347 font-weight: 600;
348 margin-bottom: 0.35rem;
349 }
350 .pubform__field input,
351 .pubform__field textarea {
352 width: 100%;
353 box-sizing: border-box;
354 padding: 0.6rem 0.7rem;
355 border: 1px solid var(--line-strong);
356 border-radius: 8px;
357 font: inherit;
358 }
359 .pubform__field textarea {
360 resize: vertical;
361 }
362 .pubform__note {
363 font-size: 0.82rem;
364 color: var(--muted);
365 }
366 .pubform__note code,
367 .dash__danger code {
368 font-family: var(--font-mono);
369 }
370 .pubform__error {
371 color: var(--ember);
372 font-size: 0.9rem;
373 }
374 .pubform__themes {
375 border: 0;
376 margin: 0 0 1rem;
377 padding: 0;
378 min-width: 0;
379 }
380 .pubform__themes legend {
381 font-size: 0.85rem;
382 font-weight: 600;
383 padding: 0;
384 margin-bottom: 0.4rem;
385 }
386 .pubform__themes small {
387 display: block;
388 margin-top: 0.5rem;
389 font-size: 0.82rem;
390 color: var(--muted);
391 }
392 .pubform__theme-grid {
393 display: grid;
394 grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
395 gap: 0.6rem;
396 }
397 .pubform__theme {
398 display: flex;
399 flex-direction: column;
400 align-items: center;
401 gap: 0.35rem;
402 cursor: pointer;
403 }
404 .pubform__theme input {
405 position: absolute;
406 width: 1px;
407 height: 1px;
408 opacity: 0;
409 pointer-events: none;
410 }
411 .pubform__theme-swatch {
412 display: flex;
413 align-items: center;
414 justify-content: center;
415 gap: 0.3rem;
416 width: 100%;
417 aspect-ratio: 16 / 10;
418 border-radius: var(--radius-sm);
419 border: 2px solid var(--line-strong);
420 font-family: var(--font-display);
421 font-weight: 600;
422 font-size: 0.95rem;
423 }
424 .pubform__theme.is-selected .pubform__theme-swatch {
425 border-color: var(--sun);
426 box-shadow: 0 0 0 2px var(--sun);
427 }
428 .pubform__theme input:focus-visible + .pubform__theme-swatch {
429 outline: 2px solid var(--sun);
430 outline-offset: 2px;
431 }
432 .pubform__theme-swatch--none {
433 background: repeating-linear-gradient(
434 45deg,
435 var(--panel),
436 var(--panel) 6px,
437 var(--paper-raised) 6px,
438 var(--paper-raised) 12px
439 );
440 }
441 .pubform__theme-dot {
442 width: 0.7rem;
443 height: 0.7rem;
444 border-radius: 50%;
445 }
446 .pubform__theme-label {
447 font-size: 0.8rem;
448 color: var(--ink-soft);
449 }
450 .pubform__actions {
451 display: flex;
452 gap: 0.75rem;
453 margin-top: 1.25rem;
454 }
455 .pubform__save {
456 border: 0;
457 border-radius: 8px;
458 background: var(--sun);
459 color: #fff;
460 font: inherit;
461 font-weight: 600;
462 padding: 0.55rem 1.1rem;
463 cursor: pointer;
464 }
465 .pubform__save:disabled {
466 opacity: 0.6;
467 cursor: not-allowed;
468 }
469 .pubform__cancel {
470 border: 1px solid var(--line-strong);
471 background: var(--paper-raised);
472 border-radius: 8px;
473 padding: 0.55rem 1rem;
474 font: inherit;
475 cursor: pointer;
476 }
477</style>