@rmdes/indiekit-endpoint-activitypub 3.8.6 → 3.9.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 (52) hide show
  1. package/assets/css/base.css +144 -0
  2. package/assets/css/card.css +377 -0
  3. package/assets/css/compose.css +169 -0
  4. package/assets/css/dark-mode.css +94 -0
  5. package/assets/css/explore.css +530 -0
  6. package/assets/css/features.css +436 -0
  7. package/assets/css/federation.css +242 -0
  8. package/assets/css/interactions.css +236 -0
  9. package/assets/css/media.css +315 -0
  10. package/assets/css/messages.css +158 -0
  11. package/assets/css/moderation.css +119 -0
  12. package/assets/css/notifications.css +191 -0
  13. package/assets/css/profile.css +308 -0
  14. package/assets/css/responsive.css +33 -0
  15. package/assets/css/skeleton.css +74 -0
  16. package/assets/reader-interactions.js +115 -0
  17. package/assets/reader.css +20 -3439
  18. package/index.js +34 -694
  19. package/lib/batch-broadcast.js +98 -0
  20. package/lib/controllers/compose.js +5 -7
  21. package/lib/controllers/interactions-boost.js +8 -13
  22. package/lib/controllers/interactions-like.js +8 -13
  23. package/lib/federation-actions.js +70 -0
  24. package/lib/inbox-queue.js +16 -10
  25. package/lib/init-indexes.js +251 -0
  26. package/lib/item-processing.js +22 -2
  27. package/lib/lookup-cache.js +3 -0
  28. package/lib/mastodon/backfill-timeline.js +11 -2
  29. package/lib/mastodon/entities/sanitize.js +19 -88
  30. package/lib/mastodon/helpers/account-cache.js +3 -0
  31. package/lib/mastodon/helpers/enrich-accounts.js +42 -55
  32. package/lib/mastodon/router.js +31 -0
  33. package/lib/mastodon/routes/accounts.js +16 -49
  34. package/lib/mastodon/routes/media.js +6 -4
  35. package/lib/mastodon/routes/notifications.js +6 -24
  36. package/lib/mastodon/routes/oauth.js +91 -18
  37. package/lib/mastodon/routes/search.js +3 -1
  38. package/lib/mastodon/routes/statuses.js +14 -52
  39. package/lib/mastodon/routes/timelines.js +3 -6
  40. package/lib/og-unfurl.js +52 -33
  41. package/lib/storage/moderation.js +11 -2
  42. package/lib/syndicator.js +239 -0
  43. package/lib/timeline-store.js +11 -15
  44. package/package.json +2 -1
  45. package/views/activitypub-federation-mgmt.njk +2 -2
  46. package/views/activitypub-moderation.njk +1 -1
  47. package/views/activitypub-profile.njk +16 -76
  48. package/views/activitypub-reader.njk +2 -1
  49. package/views/layouts/ap-reader.njk +2 -0
  50. package/views/partials/ap-item-card.njk +14 -117
  51. package/views/partials/ap-item-content.njk +20 -0
  52. package/views/partials/ap-notification-card.njk +1 -1
package/assets/reader.css CHANGED
@@ -1,3441 +1,22 @@
1
- /**
2
- * ActivityPub Reader Styles
3
- * Card-based layout inspired by Phanpy/Elk
4
- * Uses Indiekit CSS custom properties for automatic dark mode support
1
+ /* ActivityPub Reader — CSS Bundle
2
+ * Split into feature-scoped files for maintainability.
3
+ * Each file covers one UI domain.
4
+ *
5
+ * Source files live in assets/css/ — edit there, not here.
5
6
  */
6
7
 
7
- /* ==========================================================================
8
- Breadcrumb Navigation
9
- ========================================================================== */
10
-
11
- .ap-breadcrumb {
12
- display: flex;
13
- align-items: center;
14
- gap: var(--space-xs);
15
- margin-bottom: var(--space-m);
16
- font-size: var(--font-size-s);
17
- color: var(--color-on-offset);
18
- }
19
-
20
- .ap-breadcrumb a {
21
- color: var(--color-primary-on-background);
22
- text-decoration: none;
23
- }
24
-
25
- .ap-breadcrumb a:hover {
26
- text-decoration: underline;
27
- }
28
-
29
- .ap-breadcrumb__separator {
30
- color: var(--color-on-offset);
31
- }
32
-
33
- .ap-breadcrumb__current {
34
- color: var(--color-on-background);
35
- font-weight: 600;
36
- }
37
-
38
- /* ==========================================================================
39
- Fediverse Lookup
40
- ========================================================================== */
41
-
42
- .ap-lookup {
43
- display: flex;
44
- gap: var(--space-xs);
45
- margin-bottom: var(--space-m);
46
- }
47
-
48
- .ap-lookup__input {
49
- border: var(--border-width-thin) solid var(--color-outline);
50
- border-radius: var(--border-radius-small);
51
- background: var(--color-offset);
52
- box-sizing: border-box;
53
- color: var(--color-on-background);
54
- font-family: inherit;
55
- font-size: var(--font-size-m);
56
- padding: var(--space-s) var(--space-m);
57
- width: 100%;
58
- }
59
-
60
- .ap-lookup__input::placeholder {
61
- color: var(--color-on-offset);
62
- }
63
-
64
- .ap-lookup__input:focus {
65
- outline: 2px solid var(--color-primary);
66
- outline-offset: -1px;
67
- border-color: var(--color-primary);
68
- }
69
-
70
- .ap-lookup__btn {
71
- padding: var(--space-s) var(--space-m);
72
- border: var(--border-width-thin) solid var(--color-primary);
73
- border-radius: var(--border-radius-small);
74
- background: var(--color-primary);
75
- color: var(--color-on-primary);
76
- font-size: var(--font-size-m);
77
- font-family: inherit;
78
- font-weight: 600;
79
- cursor: pointer;
80
- white-space: nowrap;
81
- }
82
-
83
- .ap-lookup__btn:hover {
84
- opacity: 0.9;
85
- }
86
-
87
- /* ==========================================================================
88
- Tab Navigation
89
- ========================================================================== */
90
-
91
- .ap-tabs {
92
- border-bottom: var(--border-width-thin) solid var(--color-outline);
93
- display: flex;
94
- gap: var(--space-xs);
95
- margin-bottom: var(--space-m);
96
- overflow-x: auto;
97
- -webkit-overflow-scrolling: touch;
98
- }
99
-
100
- .ap-tab {
101
- border-bottom: var(--border-width-thick) solid transparent;
102
- color: var(--color-on-offset);
103
- font-size: var(--font-size-m);
104
- padding: var(--space-s) var(--space-m);
105
- text-decoration: none;
106
- transition:
107
- color 0.2s ease,
108
- border-color 0.2s ease;
109
- white-space: nowrap;
110
- }
111
-
112
- .ap-tab:hover {
113
- color: var(--color-on-background);
114
- }
115
-
116
- .ap-tab--active {
117
- border-bottom-color: var(--color-primary);
118
- color: var(--color-primary-on-background);
119
- font-weight: 600;
120
- }
121
-
122
- .ap-tab__count {
123
- background: var(--color-offset-variant);
124
- border-radius: var(--border-radius-large);
125
- font-size: var(--font-size-xs);
126
- font-weight: 600;
127
- margin-left: var(--space-xs);
128
- padding: 1px 6px;
129
- }
130
-
131
- .ap-tab--active .ap-tab__count {
132
- background: var(--color-primary);
133
- color: var(--color-on-primary, var(--color-neutral99));
134
- }
135
-
136
- /* ==========================================================================
137
- Timeline Layout
138
- ========================================================================== */
139
-
140
- .ap-timeline {
141
- display: flex;
142
- flex-direction: column;
143
- gap: var(--space-m);
144
- }
145
-
146
- /* ==========================================================================
147
- Item Card — Base
148
- ========================================================================== */
149
-
150
- .ap-card {
151
- background: var(--color-offset);
152
- border: var(--border-width-thin) solid var(--color-outline);
153
- border-left: 3px solid var(--color-outline);
154
- border-radius: var(--border-radius-small);
155
- overflow: hidden;
156
- padding: var(--space-m);
157
- box-shadow: 0 1px 2px hsl(var(--tint-neutral) 10% / 0.04);
158
- transition:
159
- box-shadow 0.2s ease,
160
- border-color 0.2s ease;
161
- }
162
-
163
- .ap-card:hover {
164
- border-color: var(--color-outline-variant);
165
- border-left-color: var(--color-outline-variant);
166
- box-shadow: 0 2px 8px hsl(var(--tint-neutral) 10% / 0.08);
167
- }
168
-
169
- /* ==========================================================================
170
- Item Card — Post Type Differentiation
171
- ========================================================================== */
172
-
173
- /* Notes: default purple-ish accent (the most common type) */
174
- .ap-card--note {
175
- border-left-color: var(--color-purple45);
176
- }
177
-
178
- .ap-card--note:hover {
179
- border-left-color: var(--color-purple45);
180
- }
181
-
182
- /* Articles: green accent (long-form content stands out) */
183
- .ap-card--article {
184
- border-left-color: var(--color-green50);
185
- }
186
-
187
- .ap-card--article:hover {
188
- border-left-color: var(--color-green50);
189
- }
190
-
191
- /* Boosts: yellow accent (shared content) */
192
- .ap-card--boost {
193
- border-left-color: var(--color-yellow50);
194
- }
195
-
196
- .ap-card--boost:hover {
197
- border-left-color: var(--color-yellow50);
198
- }
199
-
200
- /* Replies: blue accent (via primary color) */
201
- .ap-card--reply {
202
- border-left-color: var(--color-primary);
203
- }
204
-
205
- .ap-card--reply:hover {
206
- border-left-color: var(--color-primary);
207
- }
208
-
209
- /* ==========================================================================
210
- Boost Header
211
- ========================================================================== */
212
-
213
- .ap-card__boost {
214
- color: var(--color-on-offset);
215
- font-size: var(--font-size-s);
216
- margin-bottom: var(--space-s);
217
- padding-bottom: var(--space-xs);
218
- }
219
-
220
- .ap-card__boost a {
221
- color: var(--color-on-offset);
222
- font-weight: 600;
223
- text-decoration: none;
224
- }
225
-
226
- .ap-card__boost a:hover {
227
- color: var(--color-on-background);
228
- text-decoration: underline;
229
- }
230
-
231
- /* ==========================================================================
232
- Reply Context
233
- ========================================================================== */
234
-
235
- .ap-card__reply-to {
236
- color: var(--color-on-offset);
237
- font-size: var(--font-size-s);
238
- margin-bottom: var(--space-s);
239
- overflow: hidden;
240
- text-overflow: ellipsis;
241
- white-space: nowrap;
242
- }
243
-
244
- .ap-card__reply-to a {
245
- color: var(--color-primary-on-background);
246
- text-decoration: none;
247
- }
248
-
249
- .ap-card__reply-to a:hover {
250
- text-decoration: underline;
251
- }
252
-
253
- /* ==========================================================================
254
- Author Header
255
- ========================================================================== */
256
-
257
- .ap-card__author {
258
- align-items: center;
259
- display: flex;
260
- gap: var(--space-s);
261
- margin-bottom: var(--space-s);
262
- }
263
-
264
- .ap-card__avatar-wrap {
265
- flex-shrink: 0;
266
- height: 44px;
267
- position: relative;
268
- width: 44px;
269
- }
270
-
271
- .ap-card__avatar {
272
- border: var(--border-width-thin) solid var(--color-outline);
273
- border-radius: 50%;
274
- height: 44px;
275
- object-fit: cover;
276
- width: 44px;
277
- }
278
-
279
- .ap-card__avatar-wrap > img {
280
- position: absolute;
281
- inset: 0;
282
- z-index: 1;
283
- }
284
-
285
- .ap-card__avatar--default {
286
- align-items: center;
287
- background: var(--color-offset-variant);
288
- color: var(--color-on-offset);
289
- display: inline-flex;
290
- font-size: 1.1em;
291
- font-weight: 600;
292
- justify-content: center;
293
- }
294
-
295
- .ap-card__author-info {
296
- display: flex;
297
- flex-direction: column;
298
- flex: 1;
299
- gap: 1px;
300
- min-width: 0;
301
- }
302
-
303
- .ap-card__author-name {
304
- font-size: 0.95em;
305
- font-weight: 600;
306
- overflow: hidden;
307
- text-overflow: ellipsis;
308
- white-space: nowrap;
309
- }
310
-
311
- .ap-card__author-name a {
312
- color: inherit;
313
- text-decoration: none;
314
- }
315
-
316
- .ap-card__author-name a:hover {
317
- text-decoration: underline;
318
- }
319
-
320
- .ap-card__bot-badge {
321
- display: inline-block;
322
- font-size: 0.6rem;
323
- font-weight: 700;
324
- line-height: 1;
325
- padding: 0.15em 0.35em;
326
- margin-left: 0.3em;
327
- border: var(--border-width-thin) solid var(--color-on-offset);
328
- border-radius: var(--border-radius-small);
329
- color: var(--color-on-offset);
330
- vertical-align: middle;
331
- text-transform: uppercase;
332
- letter-spacing: 0.03em;
333
- }
334
-
335
- .ap-card__author-handle {
336
- color: var(--color-on-offset);
337
- font-size: var(--font-size-s);
338
- overflow: hidden;
339
- text-overflow: ellipsis;
340
- white-space: nowrap;
341
- }
342
-
343
- .ap-card__timestamp {
344
- color: var(--color-on-offset);
345
- flex-shrink: 0;
346
- font-size: var(--font-size-s);
347
- }
348
-
349
- .ap-card__edited {
350
- font-size: var(--font-size-xs);
351
- margin-left: 0.2em;
352
- }
353
-
354
- .ap-card__visibility {
355
- font-size: var(--font-size-xs);
356
- margin-left: 0.3em;
357
- opacity: 0.7;
358
- }
359
-
360
- .ap-card__timestamp-link {
361
- color: inherit;
362
- text-decoration: none;
363
- display: flex;
364
- align-items: center;
365
- gap: 0;
366
- }
367
-
368
- .ap-card__timestamp-link:hover {
369
- text-decoration: underline;
370
- color: var(--color-primary-on-background);
371
- }
372
-
373
- /* ==========================================================================
374
- Post Title (Articles)
375
- ========================================================================== */
376
-
377
- .ap-card__title {
378
- font-size: var(--font-size-l);
379
- font-weight: 600;
380
- line-height: var(--line-height-tight);
381
- margin-bottom: var(--space-s);
382
- }
383
-
384
- .ap-card__title a {
385
- color: inherit;
386
- text-decoration: none;
387
- }
388
-
389
- .ap-card__title a:hover {
390
- text-decoration: underline;
391
- }
392
-
393
- /* ==========================================================================
394
- Content
395
- ========================================================================== */
396
-
397
- .ap-card__content {
398
- color: var(--color-on-background);
399
- line-height: calc(4 / 3 * 1em);
400
- margin-bottom: var(--space-s);
401
- overflow-wrap: break-word;
402
- word-break: break-word;
403
- }
404
-
405
- .ap-card__content a {
406
- color: var(--color-primary-on-background);
407
- }
408
-
409
- .ap-card__content p {
410
- margin-bottom: var(--space-xs);
411
- }
412
-
413
- .ap-card__content p:last-child {
414
- margin-bottom: 0;
415
- }
416
-
417
- .ap-card__content blockquote {
418
- border-left: var(--border-width-thickest) solid var(--color-outline);
419
- margin: var(--space-s) 0;
420
- padding-left: var(--space-m);
421
- }
422
-
423
- .ap-card__content pre {
424
- background: var(--color-offset-variant);
425
- border-radius: var(--border-radius-small);
426
- overflow-x: auto;
427
- padding: var(--space-s);
428
- }
429
-
430
- .ap-card__content code {
431
- background: var(--color-offset-variant);
432
- border-radius: var(--border-radius-small);
433
- font-size: 0.9em;
434
- padding: 1px 4px;
435
- }
436
-
437
- .ap-card__content pre code {
438
- background: none;
439
- padding: 0;
440
- }
441
-
442
- .ap-card__content img {
443
- border-radius: var(--border-radius-small);
444
- height: auto;
445
- max-width: 100%;
446
- }
447
-
448
- /* @mentions — keep inline, style as subtle links */
449
- .ap-card__content .h-card {
450
- display: inline;
451
- }
452
-
453
- .ap-card__content .h-card a,
454
- .ap-card__content a.u-url.mention {
455
- display: inline;
456
- color: var(--color-on-offset);
457
- text-decoration: none;
458
- white-space: nowrap;
459
- }
460
-
461
- .ap-card__content .h-card a span,
462
- .ap-card__content a.u-url.mention span {
463
- display: inline;
464
- }
465
-
466
- .ap-card__content .h-card a:hover,
467
- .ap-card__content a.u-url.mention:hover {
468
- color: var(--color-primary-on-background);
469
- text-decoration: underline;
470
- }
471
-
472
- /* Hashtag mentions — keep inline, subtle styling */
473
- .ap-card__content a.mention.hashtag {
474
- display: inline;
475
- color: var(--color-on-offset);
476
- text-decoration: none;
477
- white-space: nowrap;
478
- }
479
-
480
- .ap-card__content a.mention.hashtag span {
481
- display: inline;
482
- }
483
-
484
- .ap-card__content a.mention.hashtag:hover {
485
- color: var(--color-primary-on-background);
486
- text-decoration: underline;
487
- }
488
-
489
- /* Mastodon's invisible/ellipsis spans for long URLs */
490
- .ap-card__content .invisible {
491
- display: none;
492
- }
493
-
494
- .ap-card__content .ellipsis::after {
495
- content: "…";
496
- }
497
-
498
- /* ==========================================================================
499
- Content Warning
500
- ========================================================================== */
501
-
502
- .ap-card__cw {
503
- margin-bottom: var(--space-s);
504
- }
505
-
506
- .ap-card__cw-toggle {
507
- background: var(--color-offset-variant);
508
- border: var(--border-width-thin) solid var(--color-outline);
509
- border-radius: var(--border-radius-small);
510
- color: var(--color-on-background);
511
- cursor: pointer;
512
- display: block;
513
- font-size: var(--font-size-s);
514
- padding: var(--space-s) var(--space-m);
515
- text-align: left;
516
- transition: background 0.2s ease;
517
- width: 100%;
518
- }
519
-
520
- .ap-card__cw-toggle:hover {
521
- background: var(--color-offset-variant-darker);
522
- }
523
-
524
- /* ==========================================================================
525
- Photo Gallery
526
- ========================================================================== */
527
-
528
- .ap-card__gallery {
529
- border-radius: var(--border-radius-small);
530
- display: grid;
531
- gap: 2px;
532
- margin-bottom: var(--space-s);
533
- overflow: hidden;
534
- }
535
-
536
- .ap-card__gallery-link {
537
- appearance: none;
538
- background: none;
539
- border: 0;
540
- cursor: pointer;
541
- display: block;
542
- padding: 0;
543
- position: relative;
544
- }
545
-
546
- .ap-card__gallery img {
547
- background: var(--color-offset-variant);
548
- display: block;
549
- height: 280px;
550
- object-fit: cover;
551
- width: 100%;
552
- transition: filter 0.2s ease;
553
- }
554
-
555
- @media (max-width: 480px) {
556
- .ap-card__gallery img {
557
- height: 180px;
558
- }
559
- }
560
-
561
- .ap-card__gallery-link:hover img {
562
- filter: brightness(0.92);
563
- }
564
-
565
- .ap-card__gallery-link--more::after {
566
- background: hsl(var(--tint-neutral) 10% / 0.5);
567
- bottom: 0;
568
- content: "";
569
- left: 0;
570
- position: absolute;
571
- right: 0;
572
- top: 0;
573
- }
574
-
575
- .ap-card__gallery-more {
576
- color: var(--color-neutral99);
577
- font-size: 1.5em;
578
- font-weight: 600;
579
- left: 50%;
580
- position: absolute;
581
- top: 50%;
582
- transform: translate(-50%, -50%);
583
- z-index: 1;
584
- }
585
-
586
- /* 1 photo */
587
- .ap-card__gallery--1 {
588
- grid-template-columns: 1fr;
589
- }
590
-
591
- .ap-card__gallery--1 img {
592
- height: auto;
593
- max-height: 500px;
594
- }
595
-
596
- /* 2 photos — side by side */
597
- .ap-card__gallery--2 {
598
- grid-template-columns: 1fr 1fr;
599
- }
600
-
601
- /* 3 photos — one large, two small */
602
- .ap-card__gallery--3 {
603
- grid-template-columns: 2fr 1fr;
604
- grid-template-rows: 1fr 1fr;
605
- }
606
-
607
- .ap-card__gallery--3 img:first-child {
608
- grid-row: 1 / 3;
609
- height: 100%;
610
- }
611
-
612
- /* 4+ photos — 2x2 grid */
613
- .ap-card__gallery--4 {
614
- grid-template-columns: 1fr 1fr;
615
- grid-template-rows: 1fr 1fr;
616
- }
617
-
618
- /* ==========================================================================
619
- Photo Lightbox
620
- ========================================================================== */
621
-
622
- [x-cloak] {
623
- display: none !important;
624
- }
625
-
626
- .ap-lightbox {
627
- align-items: center;
628
- background: hsl(var(--tint-neutral) 10% / 0.92);
629
- display: flex;
630
- inset: 0;
631
- justify-content: center;
632
- position: fixed;
633
- z-index: 9999;
634
- }
635
-
636
- .ap-lightbox__img {
637
- max-height: 90vh;
638
- max-width: 95vw;
639
- object-fit: contain;
640
- }
641
-
642
- .ap-lightbox__close {
643
- background: none;
644
- border: 0;
645
- color: white;
646
- cursor: pointer;
647
- font-size: 2rem;
648
- line-height: 1;
649
- padding: var(--space-s);
650
- position: absolute;
651
- right: var(--space-m);
652
- top: var(--space-m);
653
- }
654
-
655
- .ap-lightbox__close:hover {
656
- opacity: 0.7;
657
- }
658
-
659
- .ap-lightbox__prev,
660
- .ap-lightbox__next {
661
- background: none;
662
- border: 0;
663
- color: white;
664
- cursor: pointer;
665
- font-size: 3rem;
666
- line-height: 1;
667
- padding: var(--space-m);
668
- position: absolute;
669
- top: 50%;
670
- transform: translateY(-50%);
671
- }
672
-
673
- .ap-lightbox__prev {
674
- left: var(--space-s);
675
- }
676
-
677
- .ap-lightbox__next {
678
- right: var(--space-s);
679
- }
680
-
681
- .ap-lightbox__prev:hover,
682
- .ap-lightbox__next:hover {
683
- opacity: 0.7;
684
- }
685
-
686
- .ap-lightbox__counter {
687
- bottom: var(--space-m);
688
- color: white;
689
- font-size: var(--font-size-s);
690
- left: 50%;
691
- position: absolute;
692
- transform: translateX(-50%);
693
- }
694
-
695
- /* ==========================================================================
696
- Link Preview Card
697
- ========================================================================== */
698
-
699
- .ap-link-previews {
700
- margin-bottom: var(--space-s);
701
- }
702
-
703
- .ap-link-preview {
704
- display: flex;
705
- border: var(--border-width-thin) solid var(--color-outline);
706
- border-radius: var(--border-radius-small);
707
- overflow: hidden;
708
- text-decoration: none;
709
- color: inherit;
710
- transition: border-color 0.2s ease;
711
- }
712
-
713
- .ap-link-preview:hover {
714
- border-color: var(--color-primary);
715
- }
716
-
717
- .ap-link-preview__text {
718
- flex: 1;
719
- min-width: 0;
720
- padding: var(--space-s) var(--space-m);
721
- display: flex;
722
- flex-direction: column;
723
- justify-content: center;
724
- gap: 0.2em;
725
- }
726
-
727
- .ap-link-preview__title {
728
- font-weight: 600;
729
- font-size: var(--font-size-s);
730
- margin: 0;
731
- overflow: hidden;
732
- text-overflow: ellipsis;
733
- white-space: nowrap;
734
- }
735
-
736
- .ap-link-preview__desc {
737
- font-size: var(--font-size-s);
738
- color: var(--color-on-offset);
739
- margin: 0;
740
- display: -webkit-box;
741
- -webkit-line-clamp: 2;
742
- -webkit-box-orient: vertical;
743
- overflow: hidden;
744
- }
745
-
746
- .ap-link-preview__domain {
747
- font-size: var(--font-size-xs);
748
- color: var(--color-on-offset);
749
- margin: 0;
750
- display: flex;
751
- align-items: center;
752
- gap: 0.3em;
753
- }
754
-
755
- .ap-link-preview__favicon {
756
- width: 14px;
757
- height: 14px;
758
- }
759
-
760
- .ap-link-preview__image {
761
- flex-shrink: 0;
762
- width: 120px;
763
- }
764
-
765
- .ap-link-preview__image img {
766
- display: block;
767
- width: 100%;
768
- height: 100%;
769
- object-fit: cover;
770
- }
771
-
772
- /* ==========================================================================
773
- Video Embed
774
- ========================================================================== */
775
-
776
- .ap-card__video {
777
- margin-bottom: var(--space-s);
778
- }
779
-
780
- .ap-card__video video {
781
- border-radius: var(--border-radius-small);
782
- max-height: 400px;
783
- width: 100%;
784
- }
785
-
786
- /* ==========================================================================
787
- Audio Player
788
- ========================================================================== */
789
-
790
- .ap-card__audio {
791
- margin-bottom: var(--space-s);
792
- }
793
-
794
- .ap-card__audio audio {
795
- width: 100%;
796
- }
797
-
798
- /* ==========================================================================
799
- Tags
800
- ========================================================================== */
801
-
802
- .ap-card__tags {
803
- display: flex;
804
- flex-wrap: wrap;
805
- gap: var(--space-xs);
806
- margin-bottom: var(--space-s);
807
- }
808
-
809
- .ap-card__tag {
810
- background: var(--color-offset-variant);
811
- border-radius: var(--border-radius-large);
812
- color: var(--color-on-offset);
813
- font-size: var(--font-size-s);
814
- padding: 2px var(--space-xs);
815
- text-decoration: none;
816
- }
817
-
818
- .ap-card__tag:hover {
819
- background: var(--color-offset-variant-darker);
820
- color: var(--color-on-background);
821
- }
822
-
823
- .ap-card__mention {
824
- background: color-mix(in srgb, var(--color-primary) 12%, transparent);
825
- border-radius: var(--border-radius-large);
826
- color: var(--color-primary-on-background);
827
- font-size: var(--font-size-s);
828
- padding: 2px var(--space-xs);
829
- text-decoration: none;
830
- }
831
-
832
- .ap-card__mention:hover {
833
- background: color-mix(in srgb, var(--color-primary) 22%, transparent);
834
- color: var(--color-primary-on-background);
835
- }
836
-
837
- .ap-card__mention--legacy {
838
- cursor: default;
839
- opacity: 0.7;
840
- }
841
-
842
- /* Hashtag stuffing collapse */
843
- .ap-hashtag-overflow {
844
- margin: var(--space-xs) 0;
845
- font-size: var(--font-size-s);
846
- }
847
-
848
- .ap-hashtag-overflow summary {
849
- cursor: pointer;
850
- color: var(--color-on-offset);
851
- list-style: none;
852
- }
853
-
854
- .ap-hashtag-overflow summary::before {
855
- content: "▸ ";
856
- }
857
-
858
- .ap-hashtag-overflow[open] summary::before {
859
- content: "▾ ";
860
- }
861
-
862
- .ap-hashtag-overflow p {
863
- margin-top: var(--space-xs);
864
- }
865
-
866
- /* ==========================================================================
867
- Interaction Buttons
868
- ========================================================================== */
869
-
870
- .ap-card__actions {
871
- border-top: var(--border-width-thin) solid var(--color-outline);
872
- display: flex;
873
- flex-wrap: wrap;
874
- gap: 2px;
875
- padding-top: var(--space-s);
876
- }
877
-
878
- .ap-card__action {
879
- align-items: center;
880
- background: transparent;
881
- border: 0;
882
- border-radius: var(--border-radius-small);
883
- color: var(--color-on-offset);
884
- cursor: pointer;
885
- display: inline-flex;
886
- font-size: var(--font-size-s);
887
- gap: 0.3em;
888
- min-height: 36px;
889
- padding: 0.25em 0.6em;
890
- text-decoration: none;
891
- transition:
892
- background-color 0.15s ease,
893
- color 0.15s ease;
894
- }
895
-
896
- .ap-card__action:hover {
897
- background: var(--color-offset-variant);
898
- color: var(--color-on-background);
899
- }
900
-
901
- /* Color-coded hover states per action type */
902
- .ap-card__action--reply:hover {
903
- background: color-mix(in srgb, var(--color-primary) 12%, transparent);
904
- color: var(--color-primary);
905
- }
906
-
907
- .ap-card__action--boost:hover {
908
- background: color-mix(in srgb, var(--color-green50) 12%, transparent);
909
- color: var(--color-green50);
910
- }
911
-
912
- .ap-card__action--like:hover {
913
- background: color-mix(in srgb, var(--color-red45) 12%, transparent);
914
- color: var(--color-red45);
915
- }
916
-
917
- .ap-card__action--link:hover {
918
- background: var(--color-offset-variant);
919
- color: var(--color-on-background);
920
- }
921
-
922
- .ap-card__action--save:hover {
923
- background: color-mix(in srgb, var(--color-primary) 12%, transparent);
924
- color: var(--color-primary);
925
- }
926
-
927
- /* Active interaction states */
928
- .ap-card__action--like.ap-card__action--active {
929
- background: color-mix(in srgb, var(--color-red45) 12%, transparent);
930
- color: var(--color-red45);
931
- }
932
-
933
- .ap-card__action--boost.ap-card__action--active {
934
- background: color-mix(in srgb, var(--color-green50) 12%, transparent);
935
- color: var(--color-green50);
936
- }
937
-
938
- .ap-card__action--save.ap-card__action--active {
939
- background: color-mix(in srgb, var(--color-primary) 12%, transparent);
940
- color: var(--color-primary);
941
- }
942
-
943
- .ap-card__action:disabled {
944
- cursor: wait;
945
- opacity: 0.5;
946
- }
947
-
948
- /* Interaction counts */
949
- .ap-card__count {
950
- font-size: var(--font-size-xs);
951
- color: inherit;
952
- opacity: 0.7;
953
- margin-left: 0.1em;
954
- font-variant-numeric: tabular-nums;
955
- }
956
-
957
- /* Error message */
958
- .ap-card__action-error {
959
- color: var(--color-error);
960
- font-size: var(--font-size-s);
961
- width: 100%;
962
- }
963
-
964
- /* ==========================================================================
965
- Pagination
966
- ========================================================================== */
967
-
968
- .ap-pagination {
969
- border-top: var(--border-width-thin) solid var(--color-outline);
970
- display: flex;
971
- gap: var(--space-m);
972
- justify-content: space-between;
973
- margin-top: var(--space-m);
974
- padding-top: var(--space-m);
975
- }
976
-
977
- .ap-pagination a {
978
- color: var(--color-primary-on-background);
979
- text-decoration: none;
980
- }
981
-
982
- .ap-pagination a:hover {
983
- text-decoration: underline;
984
- }
985
-
986
- /* Hidden once Alpine is active (JS replaces with infinite scroll) */
987
- .ap-pagination--js-hidden {
988
- /* Shown by default for no-JS fallback — Alpine hides via display:none */
989
- }
990
-
991
- /* ==========================================================================
992
- Infinite Scroll / Load More
993
- ========================================================================== */
994
-
995
- .ap-load-more {
996
- display: flex;
997
- flex-direction: column;
998
- align-items: center;
999
- gap: var(--space-s);
1000
- padding: var(--space-m) 0;
1001
- }
1002
-
1003
- .ap-load-more__sentinel {
1004
- height: 1px;
1005
- width: 100%;
1006
- }
1007
-
1008
- .ap-load-more__btn {
1009
- background: var(--color-offset);
1010
- border: var(--border-width-thin) solid var(--color-outline);
1011
- border-radius: var(--border-radius-small);
1012
- color: var(--color-on-background);
1013
- cursor: pointer;
1014
- font-size: var(--font-size-s);
1015
- padding: var(--space-xs) var(--space-m);
1016
- transition: background 0.15s;
1017
- }
1018
-
1019
- .ap-load-more__btn:hover:not(:disabled) {
1020
- background: var(--color-offset-variant);
1021
- }
1022
-
1023
- .ap-load-more__btn:disabled {
1024
- cursor: wait;
1025
- opacity: 0.6;
1026
- }
1027
-
1028
- .ap-load-more__done {
1029
- color: var(--color-on-offset);
1030
- font-size: var(--font-size-s);
1031
- margin: 0;
1032
- text-align: center;
1033
- }
1034
-
1035
- /* ==========================================================================
1036
- Compose Form
1037
- ========================================================================== */
1038
-
1039
- .ap-compose__context {
1040
- background: var(--color-offset);
1041
- border-left: var(--border-width-thickest) solid var(--color-primary);
1042
- border-radius: var(--border-radius-small);
1043
- margin-bottom: var(--space-m);
1044
- padding: var(--space-m);
1045
- }
1046
-
1047
- .ap-compose__context-label {
1048
- color: var(--color-on-offset);
1049
- font-size: var(--font-size-s);
1050
- margin-bottom: var(--space-xs);
1051
- }
1052
-
1053
- .ap-compose__context-author a {
1054
- font-weight: 600;
1055
- text-decoration: none;
1056
- }
1057
-
1058
- .ap-compose__context-text {
1059
- border: 0;
1060
- font-size: var(--font-size-s);
1061
- line-height: var(--line-height-loose);
1062
- margin: var(--space-xs) 0;
1063
- padding: 0;
1064
- }
1065
-
1066
- .ap-compose__context-link {
1067
- color: var(--color-on-offset);
1068
- font-size: var(--font-size-s);
1069
- overflow: hidden;
1070
- text-overflow: ellipsis;
1071
- white-space: nowrap;
1072
- }
1073
-
1074
- .ap-compose__form {
1075
- display: flex;
1076
- flex-direction: column;
1077
- gap: var(--space-m);
1078
- }
1079
-
1080
- .ap-compose__editor {
1081
- position: relative;
1082
- }
1083
-
1084
- .ap-compose__textarea {
1085
- background: var(--color-background);
1086
- border: var(--border-width-thick) solid var(--color-outline);
1087
- border-radius: var(--border-radius-small);
1088
- color: var(--color-on-background);
1089
- font-family: inherit;
1090
- font-size: var(--font-size-m);
1091
- line-height: var(--line-height-prose);
1092
- padding: var(--space-s);
1093
- resize: vertical;
1094
- width: 100%;
1095
- }
1096
-
1097
- .ap-compose__textarea:focus {
1098
- border-color: var(--color-primary);
1099
- outline: var(--border-width-thick) solid var(--color-primary);
1100
- outline-offset: -2px;
1101
- }
1102
-
1103
- .ap-compose__cw {
1104
- display: flex;
1105
- flex-direction: column;
1106
- gap: var(--space-xs);
1107
- }
1108
-
1109
- .ap-compose__cw-toggle {
1110
- cursor: pointer;
1111
- display: flex;
1112
- align-items: center;
1113
- gap: var(--space-xs);
1114
- font-size: var(--font-size-s);
1115
- color: var(--color-on-offset);
1116
- }
1117
-
1118
- .ap-compose__cw-input {
1119
- border: var(--border-width-thin) solid var(--color-outline);
1120
- border-radius: var(--border-radius-small);
1121
- background: var(--color-offset);
1122
- color: var(--color-on-background);
1123
- font: inherit;
1124
- font-size: var(--font-size-s);
1125
- padding: var(--space-s);
1126
- width: 100%;
1127
- }
1128
-
1129
- .ap-compose__cw-input:focus {
1130
- border-color: var(--color-primary);
1131
- outline: none;
1132
- }
1133
-
1134
- .ap-compose__visibility {
1135
- border: var(--border-width-thin) solid var(--color-outline);
1136
- border-radius: var(--border-radius-small);
1137
- display: flex;
1138
- flex-wrap: wrap;
1139
- gap: var(--space-s) var(--space-m);
1140
- padding: var(--space-m);
1141
- }
1142
-
1143
- .ap-compose__visibility legend {
1144
- font-weight: 600;
1145
- }
1146
-
1147
- .ap-compose__visibility-option {
1148
- cursor: pointer;
1149
- display: flex;
1150
- align-items: center;
1151
- gap: var(--space-xs);
1152
- font-size: var(--font-size-s);
1153
- }
1154
-
1155
- .ap-compose__syndication {
1156
- border: var(--border-width-thin) solid var(--color-outline);
1157
- border-radius: var(--border-radius-small);
1158
- display: flex;
1159
- flex-direction: column;
1160
- gap: var(--space-xs);
1161
- padding: var(--space-m);
1162
- }
1163
-
1164
- .ap-compose__syndication legend {
1165
- font-weight: 600;
1166
- }
1167
-
1168
- .ap-compose__syndication-target {
1169
- cursor: pointer;
1170
- display: flex;
1171
- gap: var(--space-xs);
1172
- }
1173
-
1174
- .ap-compose__actions {
1175
- align-items: center;
1176
- display: flex;
1177
- gap: var(--space-m);
1178
- }
1179
-
1180
- .ap-compose__submit {
1181
- background: var(--color-primary);
1182
- border: 0;
1183
- border-radius: var(--border-radius-small);
1184
- color: var(--color-on-primary, var(--color-neutral99));
1185
- cursor: pointer;
1186
- font-size: var(--font-size-m);
1187
- font-weight: 600;
1188
- padding: var(--space-s) var(--space-l);
1189
- }
1190
-
1191
- .ap-compose__submit:hover {
1192
- opacity: 0.9;
1193
- }
1194
-
1195
- .ap-compose__cancel {
1196
- color: var(--color-on-offset);
1197
- text-decoration: none;
1198
- }
1199
-
1200
- .ap-compose__cancel:hover {
1201
- color: var(--color-on-background);
1202
- text-decoration: underline;
1203
- }
1204
-
1205
- /* ==========================================================================
1206
- Notifications
1207
- ========================================================================== */
1208
-
1209
- /* Notifications Toolbar */
1210
- .ap-notifications__toolbar {
1211
- display: flex;
1212
- gap: var(--space-s);
1213
- margin-bottom: var(--space-m);
1214
- }
1215
-
1216
- .ap-notifications__btn {
1217
- background: var(--color-offset);
1218
- border: var(--border-width-thin) solid var(--color-outline);
1219
- border-radius: var(--border-radius-small);
1220
- color: var(--color-on-background);
1221
- cursor: pointer;
1222
- font-size: var(--font-size-s);
1223
- padding: var(--space-xs) var(--space-m);
1224
- transition: all 0.2s ease;
1225
- }
1226
-
1227
- .ap-notifications__btn:hover {
1228
- background: var(--color-offset-variant);
1229
- border-color: var(--color-outline-variant);
1230
- }
1231
-
1232
- .ap-notifications__btn--danger {
1233
- color: var(--color-error);
1234
- }
1235
-
1236
- .ap-notifications__btn--danger:hover {
1237
- border-color: var(--color-error);
1238
- }
1239
-
1240
- .ap-notification {
1241
- align-items: flex-start;
1242
- background: var(--color-offset);
1243
- border: var(--border-width-thin) solid var(--color-outline);
1244
- border-radius: var(--border-radius-small);
1245
- display: flex;
1246
- gap: var(--space-s);
1247
- padding: var(--space-m);
1248
- position: relative;
1249
- }
1250
-
1251
- .ap-notification--unread {
1252
- border-color: var(--color-yellow50);
1253
- box-shadow: 0 0 8px 0 hsl(var(--tint-yellow) 50% / 0.3);
1254
- }
1255
-
1256
- .ap-notification__avatar-wrap {
1257
- flex-shrink: 0;
1258
- position: relative;
1259
- }
1260
-
1261
- .ap-notification__avatar-wrap {
1262
- height: 40px;
1263
- width: 40px;
1264
- }
1265
-
1266
- .ap-notification__avatar {
1267
- border: var(--border-width-thin) solid var(--color-outline);
1268
- border-radius: 50%;
1269
- height: 40px;
1270
- object-fit: cover;
1271
- width: 40px;
1272
- }
1273
-
1274
- .ap-notification__avatar-wrap > img {
1275
- position: absolute;
1276
- inset: 0;
1277
- z-index: 1;
1278
- }
1279
-
1280
- .ap-notification__avatar--default {
1281
- align-items: center;
1282
- background: var(--color-offset-variant);
1283
- color: var(--color-on-offset);
1284
- display: inline-flex;
1285
- font-size: 1.1em;
1286
- font-weight: 600;
1287
- justify-content: center;
1288
- }
1289
-
1290
- .ap-notification__type-badge {
1291
- bottom: -2px;
1292
- font-size: 0.75em;
1293
- position: absolute;
1294
- right: -4px;
1295
- }
1296
-
1297
- .ap-notification__body {
1298
- flex: 1;
1299
- min-width: 0;
1300
- }
1301
-
1302
- .ap-notification__actor {
1303
- font-weight: 600;
1304
- }
1305
-
1306
- .ap-notification__action {
1307
- color: var(--color-on-offset);
1308
- }
1309
-
1310
- .ap-notification__target {
1311
- color: var(--color-on-offset);
1312
- display: block;
1313
- font-size: var(--font-size-s);
1314
- margin-top: var(--space-xs);
1315
- overflow: hidden;
1316
- text-overflow: ellipsis;
1317
- white-space: nowrap;
1318
- }
1319
-
1320
- .ap-notification__excerpt {
1321
- background: var(--color-offset-variant);
1322
- border-radius: var(--border-radius-small);
1323
- font-size: var(--font-size-s);
1324
- margin-top: var(--space-xs);
1325
- padding: var(--space-xs) var(--space-s);
1326
- }
1327
-
1328
- .ap-notification__time {
1329
- color: var(--color-on-offset);
1330
- flex-shrink: 0;
1331
- font-size: var(--font-size-xs);
1332
- }
1333
-
1334
- .ap-notification__dismiss {
1335
- position: absolute;
1336
- right: var(--space-xs);
1337
- top: var(--space-xs);
1338
- }
1339
-
1340
- .ap-notification__dismiss-btn {
1341
- background: transparent;
1342
- border: 0;
1343
- border-radius: var(--border-radius-small);
1344
- color: var(--color-on-offset);
1345
- cursor: pointer;
1346
- font-size: var(--font-size-m);
1347
- line-height: 1;
1348
- padding: 2px 6px;
1349
- transition: all 0.2s ease;
1350
- }
1351
-
1352
- .ap-notification__dismiss-btn:hover {
1353
- background: var(--color-offset-variant);
1354
- color: var(--color-error);
1355
- }
1356
-
1357
- .ap-notification__actions {
1358
- display: flex;
1359
- gap: var(--space-s);
1360
- margin-top: var(--space-s);
1361
- }
1362
-
1363
- .ap-notification__reply-btn,
1364
- .ap-notification__thread-btn {
1365
- border: var(--border-width-thin) solid var(--color-outline);
1366
- border-radius: var(--border-radius-small);
1367
- color: var(--color-on-offset);
1368
- font-size: var(--font-size-s);
1369
- padding: var(--space-xs) var(--space-s);
1370
- text-decoration: none;
1371
- transition: all 0.2s ease;
1372
- }
1373
-
1374
- .ap-notification__reply-btn:hover,
1375
- .ap-notification__thread-btn:hover {
1376
- background: var(--color-offset-variant);
1377
- border-color: var(--color-outline-variant);
1378
- color: var(--color-on-background);
1379
- }
1380
-
1381
- .ap-notification__handle {
1382
- color: var(--color-on-offset);
1383
- font-size: var(--font-size-s);
1384
- margin-left: var(--space-xs);
1385
- }
1386
-
1387
- .ap-notifications__btn--primary {
1388
- background: var(--color-primary);
1389
- color: var(--color-on-primary, #fff);
1390
- text-decoration: none;
1391
- }
1392
-
1393
- .ap-notifications__btn--primary:hover {
1394
- opacity: 0.9;
1395
- }
1396
-
1397
- /* ==========================================================================
1398
- Messages
1399
- ========================================================================== */
1400
-
1401
- .ap-messages__layout {
1402
- display: grid;
1403
- grid-template-columns: 240px 1fr;
1404
- gap: var(--space-m);
1405
- min-height: 300px;
1406
- }
1407
-
1408
- .ap-messages__sidebar {
1409
- border-right: var(--border-width-thin) solid var(--color-outline);
1410
- display: flex;
1411
- flex-direction: column;
1412
- gap: 2px;
1413
- padding-right: var(--space-m);
1414
- overflow-y: auto;
1415
- max-height: 70vh;
1416
- }
1417
-
1418
- .ap-messages__partner {
1419
- align-items: center;
1420
- border-radius: var(--border-radius-small);
1421
- color: var(--color-on-background);
1422
- display: flex;
1423
- gap: var(--space-s);
1424
- padding: var(--space-s);
1425
- text-decoration: none;
1426
- transition: background 0.15s ease;
1427
- }
1428
-
1429
- .ap-messages__partner:hover {
1430
- background: var(--color-offset);
1431
- }
1432
-
1433
- .ap-messages__partner--active {
1434
- background: var(--color-offset);
1435
- border-left: 3px solid var(--color-primary);
1436
- font-weight: var(--font-weight-bold);
1437
- }
1438
-
1439
- .ap-messages__partner-avatar {
1440
- flex-shrink: 0;
1441
- height: 32px;
1442
- position: relative;
1443
- width: 32px;
1444
- }
1445
-
1446
- .ap-messages__partner-avatar img {
1447
- border-radius: 50%;
1448
- height: 100%;
1449
- object-fit: cover;
1450
- position: absolute;
1451
- inset: 0;
1452
- width: 100%;
1453
- z-index: 1;
1454
- }
1455
-
1456
- .ap-messages__partner-initial {
1457
- align-items: center;
1458
- background: var(--color-offset-variant);
1459
- border-radius: 50%;
1460
- color: var(--color-on-offset);
1461
- display: flex;
1462
- font-size: var(--font-size-s);
1463
- height: 100%;
1464
- justify-content: center;
1465
- width: 100%;
1466
- }
1467
-
1468
- .ap-messages__partner-info {
1469
- display: flex;
1470
- flex-direction: column;
1471
- min-width: 0;
1472
- overflow: hidden;
1473
- }
1474
-
1475
- .ap-messages__partner-name {
1476
- font-size: var(--font-size-s);
1477
- overflow: hidden;
1478
- text-overflow: ellipsis;
1479
- white-space: nowrap;
1480
- }
1481
-
1482
- .ap-messages__partner-handle {
1483
- color: var(--color-on-offset);
1484
- font-size: var(--font-size-xs);
1485
- overflow: hidden;
1486
- text-overflow: ellipsis;
1487
- white-space: nowrap;
1488
- }
1489
-
1490
- .ap-messages__content {
1491
- min-width: 0;
1492
- }
1493
-
1494
- .ap-message--outbound {
1495
- border-left: 3px solid var(--color-primary);
1496
- }
1497
-
1498
- .ap-message .ap-notification__time {
1499
- padding-right: var(--space-l);
1500
- }
1501
-
1502
- .ap-message__direction {
1503
- color: var(--color-on-offset);
1504
- font-size: var(--font-size-s);
1505
- margin-right: var(--space-xs);
1506
- }
1507
-
1508
- .ap-message__content {
1509
- color: var(--color-on-background);
1510
- font-size: var(--font-size-s);
1511
- line-height: 1.5;
1512
- margin-top: var(--space-xs);
1513
- }
1514
-
1515
- .ap-message__content p {
1516
- margin: 0 0 var(--space-xs);
1517
- }
1518
-
1519
- .ap-message__content p:last-child {
1520
- margin-bottom: 0;
1521
- }
1522
-
1523
- /* Inline mention links in DM content (Mastodon wraps @user in span inside a link) */
1524
- .ap-message__content .h-card,
1525
- .ap-message__content a.mention,
1526
- .ap-message__content a span {
1527
- display: inline;
1528
- }
1529
-
1530
- .ap-message__content a {
1531
- overflow-wrap: break-word;
1532
- }
1533
-
1534
- @media (max-width: 640px) {
1535
- .ap-messages__layout {
1536
- grid-template-columns: 1fr;
1537
- }
1538
-
1539
- .ap-messages__sidebar {
1540
- border-bottom: var(--border-width-thin) solid var(--color-outline);
1541
- border-right: none;
1542
- flex-direction: row;
1543
- max-height: none;
1544
- overflow-x: auto;
1545
- padding-bottom: var(--space-s);
1546
- padding-right: 0;
1547
- -webkit-overflow-scrolling: touch;
1548
- }
1549
-
1550
- .ap-messages__partner {
1551
- flex-shrink: 0;
1552
- white-space: nowrap;
1553
- }
1554
- }
1555
-
1556
- /* ==========================================================================
1557
- Remote Profile
1558
- ========================================================================== */
1559
-
1560
- .ap-profile__header {
1561
- border-radius: var(--border-radius-small);
1562
- height: 200px;
1563
- margin-bottom: var(--space-m);
1564
- overflow: hidden;
1565
- }
1566
-
1567
- .ap-profile__header-img {
1568
- height: 100%;
1569
- object-fit: cover;
1570
- width: 100%;
1571
- }
1572
-
1573
- .ap-profile__info {
1574
- margin-bottom: var(--space-l);
1575
- }
1576
-
1577
- .ap-profile__avatar-wrap {
1578
- height: 80px;
1579
- margin-bottom: var(--space-s);
1580
- position: relative;
1581
- width: 80px;
1582
- }
1583
-
1584
- .ap-profile__avatar-wrap > img {
1585
- position: absolute;
1586
- inset: 0;
1587
- z-index: 1;
1588
- }
1589
-
1590
- .ap-profile__avatar {
1591
- border: var(--border-width-thickest) solid var(--color-background);
1592
- border-radius: 50%;
1593
- height: 80px;
1594
- object-fit: cover;
1595
- width: 80px;
1596
- }
1597
-
1598
- .ap-profile__avatar--placeholder {
1599
- align-items: center;
1600
- background: var(--color-offset-variant);
1601
- color: var(--color-on-offset);
1602
- display: flex;
1603
- font-size: 2em;
1604
- font-weight: 600;
1605
- justify-content: center;
1606
- }
1607
-
1608
- .ap-profile__name {
1609
- font-size: var(--font-size-xl);
1610
- margin-bottom: var(--space-xs);
1611
- }
1612
-
1613
- .ap-profile__handle {
1614
- color: var(--color-on-offset);
1615
- margin-bottom: var(--space-s);
1616
- }
1617
-
1618
- .ap-profile__bio {
1619
- line-height: var(--line-height-prose);
1620
- margin-bottom: var(--space-s);
1621
- }
1622
-
1623
- .ap-profile__bio a {
1624
- color: var(--color-primary-on-background);
1625
- }
1626
-
1627
- /* Override upstream .mention { display: grid } for bio content */
1628
- .ap-profile__bio .h-card {
1629
- display: inline;
1630
- }
1631
-
1632
- .ap-profile__bio .h-card a,
1633
- .ap-profile__bio a.u-url.mention {
1634
- display: inline;
1635
- white-space: nowrap;
1636
- }
1637
-
1638
- .ap-profile__bio .h-card a span,
1639
- .ap-profile__bio a.u-url.mention span {
1640
- display: inline;
1641
- }
1642
-
1643
- .ap-profile__bio a.mention.hashtag {
1644
- display: inline;
1645
- white-space: nowrap;
1646
- }
1647
-
1648
- .ap-profile__bio a.mention.hashtag span {
1649
- display: inline;
1650
- }
1651
-
1652
- /* Mastodon invisible/ellipsis spans for long URLs in bios */
1653
- .ap-profile__bio .invisible {
1654
- display: none;
1655
- }
1656
-
1657
- .ap-profile__bio .ellipsis::after {
1658
- content: "…";
1659
- }
1660
-
1661
- .ap-profile__actions {
1662
- display: flex;
1663
- flex-wrap: wrap;
1664
- gap: var(--space-s);
1665
- margin-top: var(--space-m);
1666
- }
1667
-
1668
- .ap-profile__action {
1669
- background: transparent;
1670
- border: var(--border-width-thin) solid var(--color-outline);
1671
- border-radius: var(--border-radius-small);
1672
- color: var(--color-on-background);
1673
- cursor: pointer;
1674
- font-size: var(--font-size-s);
1675
- padding: var(--space-xs) var(--space-m);
1676
- text-decoration: none;
1677
- }
1678
-
1679
- .ap-profile__action:hover {
1680
- background: var(--color-offset);
1681
- }
1682
-
1683
- .ap-profile__action--follow.ap-profile__action--active {
1684
- background: var(--color-primary);
1685
- border-color: var(--color-primary);
1686
- color: var(--color-on-primary, var(--color-neutral99));
1687
- }
1688
-
1689
- .ap-profile__action--danger:hover {
1690
- border-color: var(--color-error);
1691
- color: var(--color-error);
1692
- }
1693
-
1694
- .ap-profile__posts {
1695
- margin-top: var(--space-l);
1696
- }
1697
-
1698
- .ap-profile__posts h3 {
1699
- border-bottom: var(--border-width-thin) solid var(--color-outline);
1700
- font-size: var(--font-size-l);
1701
- margin-bottom: var(--space-m);
1702
- padding-bottom: var(--space-s);
1703
- }
1704
-
1705
- /* ==========================================================================
1706
- My Profile — Admin Profile Header
1707
- ========================================================================== */
1708
-
1709
- .ap-my-profile {
1710
- border: var(--border-width-thin) solid var(--color-outline);
1711
- border-radius: var(--border-radius-small);
1712
- margin-bottom: var(--space-m);
1713
- overflow: hidden;
1714
- }
1715
-
1716
- .ap-my-profile__header {
1717
- height: 160px;
1718
- overflow: hidden;
1719
- }
1720
-
1721
- .ap-my-profile__header-img {
1722
- height: 100%;
1723
- object-fit: cover;
1724
- width: 100%;
1725
- }
1726
-
1727
- .ap-my-profile__info {
1728
- padding: var(--space-m);
1729
- }
1730
-
1731
- .ap-my-profile__avatar-wrap {
1732
- margin-bottom: var(--space-s);
1733
- margin-top: -40px;
1734
- }
1735
-
1736
- .ap-my-profile__avatar {
1737
- border: 3px solid var(--color-background);
1738
- border-radius: 50%;
1739
- height: 72px;
1740
- object-fit: cover;
1741
- width: 72px;
1742
- }
1743
-
1744
- .ap-my-profile__avatar--placeholder {
1745
- align-items: center;
1746
- background: var(--color-offset-variant);
1747
- color: var(--color-on-offset);
1748
- display: flex;
1749
- font-size: 1.8em;
1750
- font-weight: 600;
1751
- justify-content: center;
1752
- }
1753
-
1754
- .ap-my-profile__name {
1755
- font-size: var(--font-size-xl);
1756
- margin-bottom: 0;
1757
- }
1758
-
1759
- .ap-my-profile__handle {
1760
- color: var(--color-on-offset);
1761
- font-size: var(--font-size-s);
1762
- margin-bottom: var(--space-s);
1763
- }
1764
-
1765
- .ap-my-profile__bio {
1766
- line-height: var(--line-height-prose);
1767
- margin-bottom: var(--space-s);
1768
- }
1769
-
1770
- .ap-my-profile__bio a {
1771
- color: var(--color-primary-on-background);
1772
- }
1773
-
1774
- /* Override upstream .mention { display: grid } for bio content */
1775
- .ap-my-profile__bio .h-card { display: inline; }
1776
- .ap-my-profile__bio .h-card a,
1777
- .ap-my-profile__bio a.u-url.mention { display: inline; white-space: nowrap; }
1778
- .ap-my-profile__bio .h-card a span,
1779
- .ap-my-profile__bio a.u-url.mention span { display: inline; }
1780
- .ap-my-profile__bio a.mention.hashtag { display: inline; white-space: nowrap; }
1781
- .ap-my-profile__bio a.mention.hashtag span { display: inline; }
1782
- .ap-my-profile__bio .invisible { display: none; }
1783
- .ap-my-profile__bio .ellipsis::after { content: "…"; }
1784
-
1785
- .ap-my-profile__fields {
1786
- border: var(--border-width-thin) solid var(--color-outline);
1787
- border-radius: var(--border-radius-small);
1788
- margin: var(--space-s) 0;
1789
- overflow: hidden;
1790
- }
1791
-
1792
- .ap-my-profile__field {
1793
- border-bottom: var(--border-width-thin) solid var(--color-outline);
1794
- display: grid;
1795
- grid-template-columns: 120px 1fr;
1796
- }
1797
-
1798
- .ap-my-profile__field:last-child {
1799
- border-bottom: 0;
1800
- }
1801
-
1802
- .ap-my-profile__field-name {
1803
- background: var(--color-offset);
1804
- color: var(--color-on-offset);
1805
- font-size: var(--font-size-s);
1806
- font-weight: 600;
1807
- padding: var(--space-xs) var(--space-s);
1808
- text-transform: uppercase;
1809
- letter-spacing: 0.03em;
1810
- }
1811
-
1812
- .ap-my-profile__field-value {
1813
- font-size: var(--font-size-s);
1814
- overflow: hidden;
1815
- padding: var(--space-xs) var(--space-s);
1816
- text-overflow: ellipsis;
1817
- white-space: nowrap;
1818
- }
1819
-
1820
- .ap-my-profile__field-value a {
1821
- color: var(--color-primary-on-background);
1822
- }
1823
-
1824
- .ap-my-profile__stats {
1825
- display: flex;
1826
- gap: var(--space-m);
1827
- margin-bottom: var(--space-s);
1828
- }
1829
-
1830
- .ap-my-profile__stat {
1831
- color: var(--color-on-offset);
1832
- font-size: var(--font-size-s);
1833
- text-decoration: none;
1834
- }
1835
-
1836
- .ap-my-profile__stat:hover {
1837
- color: var(--color-on-background);
1838
- }
1839
-
1840
- .ap-my-profile__stat strong {
1841
- color: var(--color-on-background);
1842
- font-weight: 600;
1843
- }
1844
-
1845
- .ap-my-profile__edit {
1846
- border: var(--border-width-thin) solid var(--color-outline);
1847
- border-radius: var(--border-radius-small);
1848
- color: var(--color-on-background);
1849
- display: inline-block;
1850
- font-size: var(--font-size-s);
1851
- padding: var(--space-xs) var(--space-m);
1852
- text-decoration: none;
1853
- }
1854
-
1855
- .ap-my-profile__edit:hover {
1856
- background: var(--color-offset);
1857
- border-color: var(--color-outline-variant);
1858
- }
1859
-
1860
- /* When no header image, don't offset avatar */
1861
- .ap-my-profile__info:first-child .ap-my-profile__avatar-wrap {
1862
- margin-top: 0;
1863
- }
1864
-
1865
- /* ==========================================================================
1866
- Moderation
1867
- ========================================================================== */
1868
-
1869
- .ap-moderation__section {
1870
- margin-bottom: var(--space-l);
1871
- }
1872
-
1873
- .ap-moderation__section h2 {
1874
- font-size: var(--font-size-l);
1875
- margin-bottom: var(--space-s);
1876
- }
1877
-
1878
- .ap-moderation__list {
1879
- list-style: none;
1880
- margin: 0;
1881
- padding: 0;
1882
- }
1883
-
1884
- .ap-moderation__entry {
1885
- align-items: center;
1886
- border-bottom: var(--border-width-thin) solid var(--color-outline);
1887
- display: flex;
1888
- gap: var(--space-s);
1889
- justify-content: space-between;
1890
- padding: var(--space-s) 0;
1891
- }
1892
-
1893
- .ap-moderation__entry a {
1894
- min-width: 0;
1895
- overflow: hidden;
1896
- text-overflow: ellipsis;
1897
- white-space: nowrap;
1898
- }
1899
-
1900
- .ap-moderation__remove {
1901
- background: transparent;
1902
- border: var(--border-width-thin) solid var(--color-outline);
1903
- border-radius: var(--border-radius-small);
1904
- color: var(--color-on-offset);
1905
- cursor: pointer;
1906
- flex-shrink: 0;
1907
- font-size: var(--font-size-s);
1908
- padding: var(--space-xs) var(--space-s);
1909
- }
1910
-
1911
- .ap-moderation__remove:hover {
1912
- border-color: var(--color-error);
1913
- color: var(--color-error);
1914
- }
1915
-
1916
- .ap-moderation__add-form {
1917
- display: flex;
1918
- gap: var(--space-s);
1919
- }
1920
-
1921
- .ap-moderation__input {
1922
- background: var(--color-background);
1923
- border: var(--border-width-thick) solid var(--color-outline);
1924
- border-radius: var(--border-radius-small);
1925
- color: var(--color-on-background);
1926
- flex: 1;
1927
- font-size: var(--font-size-m);
1928
- padding: var(--space-xs) var(--space-s);
1929
- }
1930
-
1931
- .ap-moderation__add-btn {
1932
- background: var(--color-offset);
1933
- border: var(--border-width-thin) solid var(--color-outline);
1934
- border-radius: var(--border-radius-small);
1935
- color: var(--color-on-background);
1936
- cursor: pointer;
1937
- font-size: var(--font-size-m);
1938
- padding: var(--space-xs) var(--space-m);
1939
- }
1940
-
1941
- .ap-moderation__add-btn:hover {
1942
- background: var(--color-offset-variant);
1943
- }
1944
-
1945
- .ap-moderation__add-btn:disabled {
1946
- cursor: not-allowed;
1947
- opacity: 0.5;
1948
- }
1949
-
1950
- .ap-moderation__error {
1951
- color: var(--color-error);
1952
- font-size: var(--font-size-s);
1953
- margin-top: var(--space-xs);
1954
- }
1955
-
1956
- .ap-moderation__empty {
1957
- color: var(--color-on-offset);
1958
- font-size: var(--font-size-s);
1959
- font-style: italic;
1960
- }
1961
-
1962
- .ap-moderation__hint {
1963
- color: var(--color-on-offset);
1964
- font-size: var(--font-size-s);
1965
- margin-bottom: var(--space-s);
1966
- }
1967
-
1968
- .ap-moderation__filter-toggle {
1969
- display: flex;
1970
- gap: var(--space-m);
1971
- }
1972
-
1973
- .ap-moderation__radio {
1974
- align-items: center;
1975
- cursor: pointer;
1976
- display: flex;
1977
- gap: var(--space-xs);
1978
- }
1979
-
1980
- .ap-moderation__radio input {
1981
- accent-color: var(--color-primary);
1982
- cursor: pointer;
1983
- }
1984
-
1985
- /* ==========================================================================
1986
- Skeleton Loaders
1987
- ========================================================================== */
1988
-
1989
- @keyframes ap-skeleton-shimmer {
1990
- 0% { background-position: 200% 0; }
1991
- 100% { background-position: -200% 0; }
1992
- }
1993
-
1994
- .ap-skeleton {
1995
- background: linear-gradient(90deg,
1996
- var(--color-offset) 25%,
1997
- var(--color-background) 50%,
1998
- var(--color-offset) 75%);
1999
- background-size: 200% 100%;
2000
- animation: ap-skeleton-shimmer 1.5s ease-in-out infinite;
2001
- border-radius: var(--border-radius-small);
2002
- }
2003
-
2004
- .ap-card--skeleton {
2005
- pointer-events: none;
2006
- }
2007
-
2008
- .ap-card--skeleton .ap-card__author {
2009
- display: flex;
2010
- align-items: center;
2011
- gap: var(--space-s);
2012
- }
2013
-
2014
- .ap-skeleton--avatar {
2015
- width: 2.5rem;
2016
- height: 2.5rem;
2017
- border-radius: 50%;
2018
- flex-shrink: 0;
2019
- }
2020
-
2021
- .ap-skeleton-lines {
2022
- flex: 1;
2023
- display: flex;
2024
- flex-direction: column;
2025
- gap: 0.4rem;
2026
- }
2027
-
2028
- .ap-skeleton--name {
2029
- height: 0.85rem;
2030
- width: 40%;
2031
- }
2032
-
2033
- .ap-skeleton--handle {
2034
- height: 0.7rem;
2035
- width: 25%;
2036
- }
2037
-
2038
- .ap-skeleton-body {
2039
- display: flex;
2040
- flex-direction: column;
2041
- gap: 0.5rem;
2042
- margin-top: var(--space-s);
2043
- }
2044
-
2045
- .ap-skeleton--line {
2046
- height: 0.75rem;
2047
- width: 100%;
2048
- }
2049
-
2050
- .ap-skeleton--short {
2051
- width: 60%;
2052
- }
2053
-
2054
- .ap-skeleton-group {
2055
- display: flex;
2056
- flex-direction: column;
2057
- gap: var(--space-m);
2058
- }
2059
-
2060
- /* ==========================================================================
2061
- Responsive
2062
- ========================================================================== */
2063
-
2064
- @media (max-width: 640px) {
2065
- .ap-tabs {
2066
- gap: 0;
2067
- }
2068
-
2069
- .ap-tab {
2070
- padding: var(--space-xs) var(--space-s);
2071
- }
2072
-
2073
- .ap-card__gallery--3 {
2074
- grid-template-columns: 1fr 1fr;
2075
- grid-template-rows: auto auto;
2076
- }
2077
-
2078
- .ap-card__gallery--3 img:first-child {
2079
- grid-column: 1 / 3;
2080
- grid-row: 1;
2081
- height: 200px;
2082
- }
2083
-
2084
- .ap-card__actions {
2085
- gap: var(--space-xs);
2086
- }
2087
-
2088
- .ap-card__action {
2089
- font-size: 0.75rem;
2090
- padding: var(--space-xs);
2091
- }
2092
- }
2093
-
2094
- /* ==========================================================================
2095
- Post Detail View — Thread Layout
2096
- ========================================================================== */
2097
-
2098
- .ap-post-detail__back {
2099
- margin-bottom: var(--space-m);
2100
- }
2101
-
2102
- .ap-post-detail__back-link {
2103
- color: var(--color-primary-on-background);
2104
- font-size: var(--font-size-s);
2105
- text-decoration: none;
2106
- }
2107
-
2108
- .ap-post-detail__back-link:hover {
2109
- text-decoration: underline;
2110
- }
2111
-
2112
- .ap-post-detail__not-found {
2113
- background: var(--color-offset);
2114
- border-radius: var(--border-radius-small);
2115
- color: var(--color-on-offset);
2116
- padding: var(--space-l);
2117
- text-align: center;
2118
- }
2119
-
2120
- .ap-post-detail__section-title {
2121
- color: var(--color-on-offset);
2122
- font-size: var(--font-size-s);
2123
- font-weight: 600;
2124
- margin: var(--space-m) 0 var(--space-s);
2125
- padding-bottom: var(--space-xs);
2126
- text-transform: uppercase;
2127
- letter-spacing: 0.05em;
2128
- }
2129
-
2130
- /* Parent posts — indented with left border to show thread chain */
2131
- .ap-post-detail__parents {
2132
- border-left: 3px solid var(--color-outline);
2133
- margin-bottom: var(--space-s);
2134
- padding-left: var(--space-m);
2135
- }
2136
-
2137
- .ap-post-detail__parent-item .ap-card {
2138
- opacity: 0.85;
2139
- }
2140
-
2141
- /* Main post — highlighted */
2142
- .ap-post-detail__main {
2143
- margin-bottom: var(--space-m);
2144
- }
2145
-
2146
- .ap-post-detail__main .ap-card {
2147
- border-color: var(--color-primary);
2148
- box-shadow: 0 0 0 1px var(--color-primary);
2149
- }
2150
-
2151
- /* ==========================================================================
2152
- Tag Timeline Header
2153
- ========================================================================== */
2154
-
2155
- .ap-tag-header {
2156
- align-items: flex-start;
2157
- background: var(--color-offset);
2158
- border-bottom: var(--border-width-thin) solid var(--color-outline);
2159
- border-radius: var(--border-radius-small);
2160
- display: flex;
2161
- gap: var(--space-m);
2162
- justify-content: space-between;
2163
- margin-bottom: var(--space-m);
2164
- padding: var(--space-m);
2165
- }
2166
-
2167
- .ap-tag-header__title {
2168
- font-size: var(--font-size-xl);
2169
- font-weight: 600;
2170
- margin: 0 0 var(--space-xs);
2171
- }
2172
-
2173
- .ap-tag-header__count {
2174
- color: var(--color-on-offset);
2175
- font-size: var(--font-size-s);
2176
- margin: 0;
2177
- }
2178
-
2179
- .ap-tag-header__actions {
2180
- align-items: center;
2181
- display: flex;
2182
- flex-shrink: 0;
2183
- gap: var(--space-s);
2184
- }
2185
-
2186
- .ap-tag-header__follow-btn {
2187
- background: var(--color-primary);
2188
- border: none;
2189
- border-radius: var(--border-radius-small);
2190
- color: var(--color-on-primary, var(--color-neutral99));
2191
- cursor: pointer;
2192
- font-size: var(--font-size-s);
2193
- padding: var(--space-xs) var(--space-s);
2194
- }
2195
-
2196
- .ap-tag-header__follow-btn:hover {
2197
- opacity: 0.85;
2198
- }
2199
-
2200
- .ap-tag-header__unfollow-btn {
2201
- background: transparent;
2202
- border: var(--border-width-thin) solid var(--color-outline);
2203
- border-radius: var(--border-radius-small);
2204
- color: var(--color-on-background);
2205
- cursor: pointer;
2206
- font-size: var(--font-size-s);
2207
- padding: var(--space-xs) var(--space-s);
2208
- }
2209
-
2210
- .ap-tag-header__unfollow-btn:hover {
2211
- border-color: var(--color-on-background);
2212
- }
2213
-
2214
- .ap-tag-header__back {
2215
- color: var(--color-on-offset);
2216
- font-size: var(--font-size-s);
2217
- text-decoration: none;
2218
- }
2219
-
2220
- .ap-tag-header__back:hover {
2221
- color: var(--color-on-background);
2222
- text-decoration: underline;
2223
- }
2224
-
2225
- @media (max-width: 640px) {
2226
- .ap-tag-header {
2227
- flex-direction: column;
2228
- gap: var(--space-s);
2229
- }
2230
-
2231
- .ap-tag-header__actions {
2232
- flex-wrap: wrap;
2233
- }
2234
- }
2235
-
2236
- /* ==========================================================================
2237
- Reader Tools Bar (Explore link, etc.)
2238
- ========================================================================== */
2239
-
2240
- .ap-reader-tools {
2241
- display: flex;
2242
- gap: var(--space-s);
2243
- justify-content: flex-end;
2244
- margin-bottom: var(--space-s);
2245
- }
2246
-
2247
- .ap-reader-tools__explore {
2248
- color: var(--color-on-offset);
2249
- font-size: var(--font-size-s);
2250
- text-decoration: none;
2251
- }
2252
-
2253
- .ap-reader-tools__explore:hover {
2254
- color: var(--color-on-background);
2255
- text-decoration: underline;
2256
- }
2257
-
2258
- /* ==========================================================================
2259
- Explore Page
2260
- ========================================================================== */
2261
-
2262
- .ap-explore-header {
2263
- margin-bottom: var(--space-m);
2264
- }
2265
-
2266
- .ap-explore-header__title {
2267
- font-size: var(--font-size-xl);
2268
- margin: 0 0 var(--space-xs);
2269
- }
2270
-
2271
- .ap-explore-header__desc {
2272
- color: var(--color-on-offset);
2273
- font-size: var(--font-size-s);
2274
- margin: 0;
2275
- }
2276
-
2277
- .ap-explore-form {
2278
- background: var(--color-offset);
2279
- border: var(--border-width-thin) solid var(--color-outline);
2280
- border-radius: var(--border-radius-small);
2281
- margin-bottom: var(--space-m);
2282
- padding: var(--space-m);
2283
- }
2284
-
2285
- .ap-explore-form__row {
2286
- align-items: center;
2287
- display: flex;
2288
- gap: var(--space-s);
2289
- flex-wrap: wrap;
2290
- }
2291
-
2292
- .ap-explore-form__input {
2293
- border: var(--border-width-thin) solid var(--color-outline);
2294
- border-radius: var(--border-radius-small);
2295
- box-sizing: border-box;
2296
- font-size: var(--font-size-m);
2297
- min-width: 0;
2298
- padding: var(--space-xs) var(--space-s);
2299
- width: 100%;
2300
- }
2301
-
2302
- .ap-explore-form__scope {
2303
- display: flex;
2304
- gap: var(--space-s);
2305
- }
2306
-
2307
- .ap-explore-form__scope-label {
2308
- align-items: center;
2309
- cursor: pointer;
2310
- display: flex;
2311
- font-size: var(--font-size-s);
2312
- gap: var(--space-xs);
2313
- }
2314
-
2315
- .ap-explore-form__btn {
2316
- background: var(--color-primary);
2317
- border: none;
2318
- border-radius: var(--border-radius-small);
2319
- color: var(--color-on-primary);
2320
- cursor: pointer;
2321
- font-size: var(--font-size-s);
2322
- padding: var(--space-xs) var(--space-m);
2323
- white-space: nowrap;
2324
- }
2325
-
2326
- .ap-explore-form__btn:hover {
2327
- opacity: 0.85;
2328
- }
2329
-
2330
- .ap-explore-error {
2331
- background: color-mix(in srgb, var(--color-error) 10%, transparent);
2332
- border: var(--border-width-thin) solid var(--color-error);
2333
- border-radius: var(--border-radius-small);
2334
- color: var(--color-error);
2335
- margin-bottom: var(--space-m);
2336
- padding: var(--space-s) var(--space-m);
2337
- }
2338
-
2339
- @media (max-width: 640px) {
2340
- .ap-explore-form__row {
2341
- flex-direction: column;
2342
- align-items: stretch;
2343
- }
2344
-
2345
- .ap-explore-form__btn {
2346
- width: 100%;
2347
- }
2348
- }
2349
-
2350
- /* ---------- Autocomplete dropdown ---------- */
2351
-
2352
- .ap-explore-autocomplete {
2353
- flex: 1;
2354
- min-width: 0;
2355
- position: relative;
2356
- }
2357
-
2358
- .ap-explore-autocomplete__dropdown {
2359
- background: var(--color-background);
2360
- border: var(--border-width-thin) solid var(--color-outline);
2361
- border-radius: var(--border-radius-small);
2362
- box-shadow: 0 4px 12px hsl(var(--tint-neutral) 10% / 0.15);
2363
- left: 0;
2364
- max-height: 320px;
2365
- overflow-y: auto;
2366
- position: absolute;
2367
- right: 0;
2368
- top: 100%;
2369
- z-index: 100;
2370
- }
2371
-
2372
- .ap-explore-autocomplete__item {
2373
- align-items: center;
2374
- background: none;
2375
- border: none;
2376
- color: var(--color-on-background);
2377
- cursor: pointer;
2378
- display: flex;
2379
- font-family: inherit;
2380
- font-size: var(--font-size-s);
2381
- gap: var(--space-s);
2382
- padding: var(--space-s) var(--space-m);
2383
- text-align: left;
2384
- width: 100%;
2385
- }
2386
-
2387
- .ap-explore-autocomplete__item:hover,
2388
- .ap-explore-autocomplete__item--highlighted {
2389
- background: var(--color-offset);
2390
- }
2391
-
2392
- .ap-explore-autocomplete__domain {
2393
- flex-shrink: 0;
2394
- font-weight: 600;
2395
- }
2396
-
2397
- .ap-explore-autocomplete__meta {
2398
- color: var(--color-on-offset);
2399
- display: flex;
2400
- flex: 1;
2401
- gap: var(--space-xs);
2402
- min-width: 0;
2403
- }
2404
-
2405
- .ap-explore-autocomplete__software {
2406
- background: color-mix(in srgb, var(--color-primary) 12%, transparent);
2407
- border-radius: var(--border-radius-small);
2408
- font-size: var(--font-size-xs);
2409
- padding: 1px 6px;
2410
- white-space: nowrap;
2411
- }
2412
-
2413
- .ap-explore-autocomplete__mau {
2414
- font-size: var(--font-size-xs);
2415
- white-space: nowrap;
2416
- }
2417
-
2418
- .ap-explore-autocomplete__status {
2419
- flex-shrink: 0;
2420
- font-size: var(--font-size-s);
2421
- }
2422
-
2423
- .ap-explore-autocomplete__checking {
2424
- opacity: 0.5;
2425
- }
2426
-
2427
- /* ---------- Popular accounts autocomplete ---------- */
2428
-
2429
- .ap-lookup-autocomplete {
2430
- flex: 1;
2431
- min-width: 0;
2432
- position: relative;
2433
- }
2434
-
2435
- .ap-lookup-autocomplete__dropdown {
2436
- background: var(--color-background);
2437
- border: var(--border-width-thin) solid var(--color-outline);
2438
- border-radius: var(--border-radius-small);
2439
- box-shadow: 0 4px 12px hsl(var(--tint-neutral) 10% / 0.15);
2440
- left: 0;
2441
- max-height: 320px;
2442
- overflow-y: auto;
2443
- position: absolute;
2444
- right: 0;
2445
- top: 100%;
2446
- z-index: 100;
2447
- }
2448
-
2449
- .ap-lookup-autocomplete__item {
2450
- align-items: center;
2451
- background: none;
2452
- border: none;
2453
- color: var(--color-on-background);
2454
- cursor: pointer;
2455
- display: flex;
2456
- font-family: inherit;
2457
- font-size: var(--font-size-s);
2458
- gap: var(--space-s);
2459
- padding: var(--space-s) var(--space-m);
2460
- text-align: left;
2461
- width: 100%;
2462
- }
2463
-
2464
- .ap-lookup-autocomplete__item:hover,
2465
- .ap-lookup-autocomplete__item--highlighted {
2466
- background: var(--color-offset);
2467
- }
2468
-
2469
- .ap-lookup-autocomplete__avatar {
2470
- border-radius: 50%;
2471
- flex-shrink: 0;
2472
- height: 28px;
2473
- object-fit: cover;
2474
- width: 28px;
2475
- }
2476
-
2477
- .ap-lookup-autocomplete__info {
2478
- display: flex;
2479
- flex: 1;
2480
- flex-direction: column;
2481
- min-width: 0;
2482
- }
2483
-
2484
- .ap-lookup-autocomplete__name {
2485
- font-weight: 600;
2486
- overflow: hidden;
2487
- text-overflow: ellipsis;
2488
- white-space: nowrap;
2489
- }
2490
-
2491
- .ap-lookup-autocomplete__handle {
2492
- color: var(--color-on-offset);
2493
- font-size: var(--font-size-xs);
2494
- overflow: hidden;
2495
- text-overflow: ellipsis;
2496
- white-space: nowrap;
2497
- }
2498
-
2499
- .ap-lookup-autocomplete__followers {
2500
- color: var(--color-on-offset);
2501
- flex-shrink: 0;
2502
- font-size: var(--font-size-xs);
2503
- white-space: nowrap;
2504
- }
2505
-
2506
- /* Replies — indented from the other side */
2507
- .ap-post-detail__replies {
2508
- margin-left: var(--space-l);
2509
- }
2510
-
2511
- .ap-post-detail__reply-item {
2512
- border-left: 2px solid var(--color-outline);
2513
- padding-left: var(--space-m);
2514
- margin-bottom: var(--space-xs);
2515
- }
2516
-
2517
- /* Followed tags bar */
2518
- .ap-followed-tags {
2519
- display: flex;
2520
- flex-wrap: wrap;
2521
- align-items: center;
2522
- gap: var(--space-xs);
2523
- padding: var(--space-xs) 0;
2524
- margin-bottom: var(--space-s);
2525
- font-size: var(--font-size-s);
2526
- }
2527
-
2528
- .ap-followed-tags__label {
2529
- color: var(--color-on-offset);
2530
- font-weight: 600;
2531
- }
2532
-
2533
- /* ==========================================================================
2534
- Explore: Tabbed Design
2535
- ========================================================================== */
2536
-
2537
- /* Tab bar wrapper: enables position:relative for fade gradient overlay */
2538
- .ap-explore-tabs-container {
2539
- position: relative;
2540
- }
2541
-
2542
- /* Tab bar with right-edge fade to indicate horizontal overflow */
2543
- .ap-explore-tabs-nav {
2544
- padding-right: var(--space-l);
2545
- position: relative;
2546
- }
2547
-
2548
- .ap-explore-tabs-nav::after {
2549
- background: linear-gradient(to right, transparent, var(--color-background) 80%);
2550
- content: "";
2551
- height: 100%;
2552
- pointer-events: none;
2553
- position: absolute;
2554
- right: 0;
2555
- top: 0;
2556
- width: 40px;
2557
- }
2558
-
2559
- /* Tab wrapper: holds tab button + reorder/close controls together */
2560
- .ap-tab-wrapper {
2561
- align-items: stretch;
2562
- display: inline-flex;
2563
- position: relative;
2564
- }
2565
-
2566
- /* Show controls on hover or when the tab is active */
2567
- .ap-tab-controls {
2568
- align-items: center;
2569
- display: none;
2570
- gap: 1px;
2571
- }
2572
-
2573
- .ap-tab-wrapper:hover .ap-tab-controls,
2574
- .ap-tab-wrapper:focus-within .ap-tab-controls {
2575
- display: flex;
2576
- }
2577
-
2578
- /* Individual control buttons (↑ ↓ ×) */
2579
- .ap-tab-control {
2580
- background: none;
2581
- border: none;
2582
- color: var(--color-on-offset);
2583
- cursor: pointer;
2584
- font-size: var(--font-size-xs);
2585
- line-height: 1;
2586
- padding: 2px 4px;
2587
- }
2588
-
2589
- .ap-tab-control:hover {
2590
- color: var(--color-on-background);
2591
- }
2592
-
2593
- .ap-tab-control:disabled {
2594
- cursor: default;
2595
- opacity: 0.3;
2596
- }
2597
-
2598
- .ap-tab-control--remove {
2599
- color: var(--color-on-offset);
2600
- font-size: var(--font-size-s);
2601
- }
2602
-
2603
- .ap-tab-control--remove:hover {
2604
- color: var(--color-error);
2605
- }
2606
-
2607
- /* Truncate long domain names in tab labels */
2608
- .ap-tab__label {
2609
- display: inline-block;
2610
- max-width: 150px;
2611
- overflow: hidden;
2612
- text-overflow: ellipsis;
2613
- white-space: nowrap;
2614
- }
2615
-
2616
- /* Scope badges on instance tabs */
2617
- .ap-tab__badge {
2618
- border-radius: var(--border-radius-small);
2619
- font-size: 0.65em;
2620
- font-weight: 700;
2621
- letter-spacing: 0.02em;
2622
- margin-left: var(--space-xs);
2623
- padding: 1px 4px;
2624
- text-transform: uppercase;
2625
- vertical-align: middle;
2626
- }
2627
-
2628
- .ap-tab__badge--local {
2629
- background: color-mix(in srgb, var(--color-primary) 15%, transparent);
2630
- color: var(--color-primary-on-background);
2631
- }
2632
-
2633
- .ap-tab__badge--federated {
2634
- background: color-mix(in srgb, var(--color-purple45) 15%, transparent);
2635
- color: var(--color-purple45);
2636
- }
2637
-
2638
- /* +# button for adding hashtag tabs */
2639
- .ap-tab--add {
2640
- font-family: monospace;
2641
- font-weight: 700;
2642
- letter-spacing: -0.05em;
2643
- }
2644
-
2645
- /* Inline hashtag form that appears when +# is clicked */
2646
- .ap-tab-add-hashtag {
2647
- align-items: center;
2648
- display: inline-flex;
2649
- gap: var(--space-xs);
2650
- }
2651
-
2652
- .ap-tab-hashtag-form {
2653
- align-items: center;
2654
- display: flex;
2655
- gap: var(--space-xs);
2656
- }
2657
-
2658
- .ap-tab-hashtag-form__prefix {
2659
- color: var(--color-on-offset);
2660
- font-weight: 600;
2661
- }
2662
-
2663
- .ap-tab-hashtag-form__input {
2664
- border: var(--border-width-thin) solid var(--color-outline);
2665
- border-radius: var(--border-radius-small);
2666
- font-family: inherit;
2667
- font-size: var(--font-size-s);
2668
- padding: 2px var(--space-s);
2669
- width: 8em;
2670
- }
2671
-
2672
- .ap-tab-hashtag-form__input:focus {
2673
- border-color: var(--color-primary);
2674
- outline: 2px solid var(--color-primary);
2675
- outline-offset: -1px;
2676
- }
2677
-
2678
- .ap-tab-hashtag-form__btn {
2679
- background: var(--color-primary);
2680
- border: none;
2681
- border-radius: var(--border-radius-small);
2682
- color: var(--color-on-primary);
2683
- cursor: pointer;
2684
- font-family: inherit;
2685
- font-size: var(--font-size-s);
2686
- padding: 2px var(--space-s);
2687
- white-space: nowrap;
2688
- }
2689
-
2690
- .ap-tab-hashtag-form__btn:hover {
2691
- opacity: 0.85;
2692
- }
2693
-
2694
- /* "Pin as tab" button in search results area */
2695
- .ap-explore-pin-bar {
2696
- margin-bottom: var(--space-s);
2697
- }
2698
-
2699
- .ap-explore-pin-btn {
2700
- background: none;
2701
- border: var(--border-width-thin) solid var(--color-primary-on-background);
2702
- border-radius: var(--border-radius-small);
2703
- color: var(--color-primary-on-background);
2704
- cursor: pointer;
2705
- font-family: inherit;
2706
- font-size: var(--font-size-s);
2707
- padding: var(--space-xs) var(--space-m);
2708
- }
2709
-
2710
- .ap-explore-pin-btn:hover {
2711
- background: color-mix(in srgb, var(--color-primary) 10%, transparent);
2712
- }
2713
-
2714
- .ap-explore-pin-btn:disabled {
2715
- cursor: default;
2716
- opacity: 0.6;
2717
- }
2718
-
2719
- /* Hashtag form row inside the search form */
2720
- .ap-explore-form__hashtag-row {
2721
- align-items: center;
2722
- display: flex;
2723
- flex-wrap: wrap;
2724
- gap: var(--space-xs);
2725
- margin-top: var(--space-s);
2726
- }
2727
-
2728
- .ap-explore-form__hashtag-label {
2729
- color: var(--color-on-offset);
2730
- font-size: var(--font-size-s);
2731
- white-space: nowrap;
2732
- }
2733
-
2734
- .ap-explore-form__hashtag-prefix {
2735
- color: var(--color-on-offset);
2736
- font-weight: 600;
2737
- }
2738
-
2739
- .ap-explore-form__hashtag-hint {
2740
- color: var(--color-on-offset);
2741
- font-size: var(--font-size-xs);
2742
- flex-basis: 100%;
2743
- }
2744
-
2745
- .ap-explore-form__input--hashtag {
2746
- max-width: 200px;
2747
- width: auto;
2748
- }
2749
-
2750
- /* Tab panel containers */
2751
- .ap-explore-instance-panel,
2752
- .ap-explore-hashtag-panel {
2753
- min-height: 120px;
2754
- }
2755
-
2756
- /* Loading state */
2757
- .ap-explore-tab-loading {
2758
- align-items: center;
2759
- color: var(--color-on-offset);
2760
- display: flex;
2761
- justify-content: center;
2762
- padding: var(--space-xl);
2763
- }
2764
-
2765
- .ap-explore-tab-loading--more {
2766
- padding-block: var(--space-m);
2767
- }
2768
-
2769
- .ap-explore-tab-loading__text {
2770
- font-size: var(--font-size-s);
2771
- }
2772
-
2773
- /* Error state */
2774
- .ap-explore-tab-error {
2775
- align-items: center;
2776
- display: flex;
2777
- flex-direction: column;
2778
- gap: var(--space-s);
2779
- padding: var(--space-xl);
2780
- }
2781
-
2782
- .ap-explore-tab-error__message {
2783
- color: var(--color-error);
2784
- font-size: var(--font-size-s);
2785
- margin: 0;
2786
- }
2787
-
2788
- .ap-explore-tab-error__retry {
2789
- background: none;
2790
- border: var(--border-width-thin) solid var(--color-primary-on-background);
2791
- border-radius: var(--border-radius-small);
2792
- color: var(--color-primary-on-background);
2793
- cursor: pointer;
2794
- font-size: var(--font-size-s);
2795
- padding: var(--space-xs) var(--space-s);
2796
- }
2797
-
2798
- .ap-explore-tab-error__retry:hover {
2799
- background: color-mix(in srgb, var(--color-primary) 10%, transparent);
2800
- }
2801
-
2802
- /* Empty state */
2803
- .ap-explore-tab-empty {
2804
- color: var(--color-on-offset);
2805
- font-size: var(--font-size-s);
2806
- padding: var(--space-xl);
2807
- text-align: center;
2808
- }
2809
-
2810
- /* Infinite scroll sentinel — zero height, invisible */
2811
- .ap-tab-sentinel {
2812
- height: 1px;
2813
- visibility: hidden;
2814
- }
2815
-
2816
- /* ==========================================================================
2817
- New Posts Banner
2818
- ========================================================================== */
2819
-
2820
- .ap-new-posts-banner {
2821
- left: 0;
2822
- position: sticky;
2823
- right: 0;
2824
- top: 0;
2825
- z-index: 10;
2826
- }
2827
-
2828
- .ap-new-posts-banner__btn {
2829
- background: var(--color-primary);
2830
- border: none;
2831
- border-radius: var(--border-radius-small);
2832
- color: var(--color-on-primary);
2833
- cursor: pointer;
2834
- display: block;
2835
- font-family: inherit;
2836
- font-size: var(--font-size-s);
2837
- margin: 0 auto var(--space-s);
2838
- padding: var(--space-xs) var(--space-m);
2839
- text-align: center;
2840
- width: auto;
2841
- }
2842
-
2843
- .ap-new-posts-banner__btn:hover {
2844
- opacity: 0.9;
2845
- }
2846
-
2847
- /* ==========================================================================
2848
- Read State
2849
- ========================================================================== */
2850
-
2851
- .ap-card--read {
2852
- opacity: 0.7;
2853
- transition: opacity 0.3s ease;
2854
- }
2855
-
2856
- .ap-card--read:hover {
2857
- opacity: 1;
2858
- }
2859
-
2860
- /* ==========================================================================
2861
- Unread Toggle
2862
- ========================================================================== */
2863
-
2864
- .ap-unread-toggle {
2865
- margin-left: auto;
2866
- }
2867
-
2868
- .ap-unread-toggle--active {
2869
- background: color-mix(in srgb, var(--color-primary) 12%, transparent);
2870
- font-weight: 600;
2871
- }
2872
-
2873
- /* ==========================================================================
2874
- Quote Embeds
2875
- ========================================================================== */
2876
-
2877
- .ap-quote-embed {
2878
- border: var(--border-width-thin) solid var(--color-outline);
2879
- border-radius: var(--border-radius-small);
2880
- margin-top: var(--space-s);
2881
- overflow: hidden;
2882
- transition: border-color 0.15s ease;
2883
- }
2884
-
2885
- .ap-quote-embed:hover {
2886
- border-color: var(--color-outline-variant);
2887
- }
2888
-
2889
- .ap-quote-embed--pending {
2890
- border-style: dashed;
2891
- }
2892
-
2893
- .ap-quote-embed__link {
2894
- color: inherit;
2895
- display: block;
2896
- padding: var(--space-s) var(--space-m);
2897
- text-decoration: none;
2898
- }
2899
-
2900
- .ap-quote-embed__link:hover {
2901
- background: color-mix(in srgb, var(--color-offset) 50%, transparent);
2902
- }
2903
-
2904
- .ap-quote-embed__author {
2905
- align-items: center;
2906
- display: flex;
2907
- gap: var(--space-xs);
2908
- margin-bottom: var(--space-xs);
2909
- }
2910
-
2911
- .ap-quote-embed__avatar {
2912
- border-radius: 50%;
2913
- flex-shrink: 0;
2914
- height: 24px;
2915
- object-fit: cover;
2916
- width: 24px;
2917
- }
2918
-
2919
- .ap-quote-embed__avatar--default {
2920
- align-items: center;
2921
- background: var(--color-offset);
2922
- color: var(--color-on-offset);
2923
- display: inline-flex;
2924
- font-size: var(--font-size-xs);
2925
- font-weight: 600;
2926
- justify-content: center;
2927
- }
2928
-
2929
- .ap-quote-embed__author-info {
2930
- flex: 1;
2931
- min-width: 0;
2932
- }
2933
-
2934
- .ap-quote-embed__name {
2935
- font-size: var(--font-size-s);
2936
- font-weight: 600;
2937
- overflow: hidden;
2938
- text-overflow: ellipsis;
2939
- white-space: nowrap;
2940
- }
2941
-
2942
- .ap-quote-embed__handle {
2943
- color: var(--color-on-offset);
2944
- font-size: var(--font-size-xs);
2945
- overflow: hidden;
2946
- text-overflow: ellipsis;
2947
- white-space: nowrap;
2948
- }
2949
-
2950
- .ap-quote-embed__time {
2951
- color: var(--color-on-offset);
2952
- flex-shrink: 0;
2953
- font-size: var(--font-size-xs);
2954
- white-space: nowrap;
2955
- }
2956
-
2957
- .ap-quote-embed__title {
2958
- font-size: var(--font-size-s);
2959
- font-weight: 600;
2960
- margin: 0 0 var(--space-xs);
2961
- }
2962
-
2963
- .ap-quote-embed__content {
2964
- color: var(--color-on-background);
2965
- font-size: var(--font-size-s);
2966
- line-height: calc(4 / 3 * 1em);
2967
- max-height: calc(1.333em * 6);
2968
- overflow: hidden;
2969
- }
2970
-
2971
- .ap-quote-embed__content a {
2972
- display: inline;
2973
- }
2974
-
2975
- .ap-quote-embed__content a span {
2976
- display: inline;
2977
- }
2978
-
2979
- .ap-quote-embed__content p {
2980
- margin: 0 0 var(--space-xs);
2981
- }
2982
-
2983
- .ap-quote-embed__content p:last-child {
2984
- margin-bottom: 0;
2985
- }
2986
-
2987
- .ap-quote-embed__media {
2988
- margin-top: var(--space-xs);
2989
- }
2990
-
2991
- .ap-quote-embed__photo {
2992
- border-radius: var(--border-radius-small);
2993
- max-height: 160px;
2994
- max-width: 100%;
2995
- object-fit: cover;
2996
- }
2997
-
2998
- /* Hashtag tab sources info line */
2999
- .ap-hashtag-sources {
3000
- color: var(--color-on-offset);
3001
- font-size: var(--font-size-s);
3002
- margin: 0;
3003
- padding: var(--space-s) 0 var(--space-xs);
3004
- }
3005
-
3006
- /* Custom emoji */
3007
- .ap-custom-emoji {
3008
- height: 1.2em;
3009
- width: auto;
3010
- vertical-align: middle;
3011
- display: inline;
3012
- margin: 0 0.05em;
3013
- }
3014
-
3015
- /* Gallery items — positioned for ALT badge overlay */
3016
- .ap-card__gallery-item {
3017
- position: relative;
3018
- }
3019
-
3020
- /* ALT text badges */
3021
- .ap-media__alt-badge {
3022
- position: absolute;
3023
- bottom: 0.5rem;
3024
- left: 0.5rem;
3025
- background: hsl(var(--tint-neutral) 10% / 0.7);
3026
- color: var(--color-neutral99);
3027
- font-size: 0.65rem;
3028
- font-weight: 700;
3029
- padding: 0.15rem 0.35rem;
3030
- border-radius: var(--border-radius-small);
3031
- border: none;
3032
- cursor: pointer;
3033
- text-transform: uppercase;
3034
- letter-spacing: 0.03em;
3035
- z-index: 1;
3036
- }
3037
-
3038
- .ap-media__alt-badge:hover {
3039
- background: hsl(var(--tint-neutral) 10% / 0.9);
3040
- }
3041
-
3042
- .ap-media__alt-text {
3043
- position: absolute;
3044
- bottom: 2.2rem;
3045
- left: 0.5rem;
3046
- right: 0.5rem;
3047
- background: hsl(var(--tint-neutral) 10% / 0.85);
3048
- color: var(--color-neutral99);
3049
- font-size: var(--font-size-s);
3050
- padding: 0.5rem;
3051
- border-radius: var(--border-radius-small);
3052
- max-height: 8rem;
3053
- overflow-y: auto;
3054
- z-index: 2;
3055
- }
3056
-
3057
- /* ==========================================================================
3058
- Poll / Question
3059
- ========================================================================== */
3060
-
3061
- .ap-poll {
3062
- margin-top: var(--space-s);
3063
- }
3064
-
3065
- .ap-poll__option {
3066
- position: relative;
3067
- padding: var(--space-xs) var(--space-s);
3068
- margin-bottom: var(--space-xs);
3069
- border-radius: var(--border-radius-small);
3070
- background: var(--color-offset);
3071
- overflow: hidden;
3072
- }
3073
-
3074
- .ap-poll__bar {
3075
- position: absolute;
3076
- top: 0;
3077
- left: 0;
3078
- bottom: 0;
3079
- background: var(--color-primary);
3080
- opacity: 0.15;
3081
- border-radius: var(--border-radius-small);
3082
- }
3083
-
3084
- .ap-poll__label {
3085
- position: relative;
3086
- font-size: var(--font-size-s);
3087
- color: var(--color-on-background);
3088
- }
3089
-
3090
- .ap-poll__votes {
3091
- position: relative;
3092
- float: right;
3093
- font-size: var(--font-size-s);
3094
- font-weight: 600;
3095
- color: var(--color-on-offset);
3096
- }
3097
-
3098
- .ap-poll__footer {
3099
- font-size: var(--font-size-xs);
3100
- color: var(--color-on-offset);
3101
- margin-top: var(--space-xs);
3102
- }
3103
-
3104
- /* ==========================================================================
3105
- Dark Mode Overrides
3106
- Softens saturated colors that are uncomfortable on dark backgrounds.
3107
- Uses Indiekit's existing light-variant tokens (red80, green90, yellow90)
3108
- which are designed for dark surfaces.
3109
- ========================================================================== */
3110
-
3111
- @media (prefers-color-scheme: dark) {
3112
-
3113
- /* --- Action button hover states: softer colors, more visible tinted backgrounds --- */
3114
- .ap-card__action--reply:hover {
3115
- background: color-mix(in srgb, var(--color-primary) 18%, transparent);
3116
- color: var(--color-primary-on-background);
3117
- }
3118
-
3119
- .ap-card__action--boost:hover {
3120
- background: color-mix(in srgb, var(--color-green50) 18%, transparent);
3121
- color: var(--color-green90);
3122
- }
3123
-
3124
- .ap-card__action--like:hover {
3125
- background: color-mix(in srgb, var(--color-red45) 18%, transparent);
3126
- color: var(--color-red80);
3127
- }
3128
-
3129
- .ap-card__action--save:hover {
3130
- background: color-mix(in srgb, var(--color-primary) 18%, transparent);
3131
- color: var(--color-primary-on-background);
3132
- }
3133
-
3134
- /* --- Active interaction states --- */
3135
- .ap-card__action--like.ap-card__action--active {
3136
- background: color-mix(in srgb, var(--color-red45) 18%, transparent);
3137
- color: var(--color-red80);
3138
- }
3139
-
3140
- .ap-card__action--boost.ap-card__action--active {
3141
- background: color-mix(in srgb, var(--color-green50) 18%, transparent);
3142
- color: var(--color-green90);
3143
- }
3144
-
3145
- .ap-card__action--save.ap-card__action--active {
3146
- background: color-mix(in srgb, var(--color-primary) 18%, transparent);
3147
- color: var(--color-primary-on-background);
3148
- }
3149
-
3150
- /* --- Post-type left border accents: desaturated for dark surfaces --- */
3151
- .ap-card--note,
3152
- .ap-card--note:hover {
3153
- border-left-color: var(--color-purple90);
3154
- }
3155
-
3156
- .ap-card--article,
3157
- .ap-card--article:hover {
3158
- border-left-color: var(--color-green90);
3159
- }
3160
-
3161
- .ap-card--boost,
3162
- .ap-card--boost:hover {
3163
- border-left-color: var(--color-yellow90);
3164
- }
3165
-
3166
- .ap-card--reply,
3167
- .ap-card--reply:hover {
3168
- border-left-color: var(--color-primary-on-background);
3169
- }
3170
-
3171
- /* --- Notification unread glow: toned down --- */
3172
- .ap-notification--unread {
3173
- border-color: var(--color-yellow90);
3174
- box-shadow: 0 0 6px 0 color-mix(in srgb, var(--color-yellow50) 15%, transparent);
3175
- }
3176
-
3177
- /* --- Post detail highlight ring: softened --- */
3178
- .ap-post-detail__main .ap-card {
3179
- border-color: color-mix(in srgb, var(--color-primary) 50%, transparent);
3180
- box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-primary) 50%, transparent);
3181
- }
3182
-
3183
- /* --- Card shadows: use light tint instead of black --- */
3184
- .ap-card {
3185
- box-shadow: 0 1px 2px hsl(var(--tint-neutral) 90% / 0.04);
3186
- }
3187
-
3188
- .ap-card:hover {
3189
- box-shadow: 0 2px 8px hsl(var(--tint-neutral) 90% / 0.06);
3190
- }
3191
-
3192
- /* --- Tab badge federated: soften purple --- */
3193
- .ap-tab__badge--federated {
3194
- color: var(--color-purple90);
3195
- background: color-mix(in srgb, var(--color-purple45) 18%, transparent);
3196
- }
3197
- }
3198
-
3199
- /* ==========================================================================
3200
- Federation Management
3201
- ========================================================================== */
3202
-
3203
- .ap-federation__section {
3204
- margin-block-end: var(--space-l);
3205
- }
3206
-
3207
- .ap-federation__section h2 {
3208
- margin-block-end: var(--space-s);
3209
- }
3210
-
3211
- .ap-federation__stats-grid {
3212
- display: grid;
3213
- grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
3214
- gap: var(--space-s);
3215
- }
3216
-
3217
- .ap-federation__stat-card {
3218
- display: flex;
3219
- flex-direction: column;
3220
- align-items: center;
3221
- gap: var(--space-xs);
3222
- padding: var(--space-s);
3223
- background: var(--color-offset);
3224
- border-radius: var(--border-radius-small);
3225
- text-align: center;
3226
- }
3227
-
3228
- .ap-federation__stat-count {
3229
- font-size: var(--font-size-xl);
3230
- font-weight: 600;
3231
- color: var(--color-on-background);
3232
- }
3233
-
3234
- .ap-federation__stat-label {
3235
- font-size: var(--font-size-s);
3236
- color: var(--color-on-offset);
3237
- word-break: break-word;
3238
- }
3239
-
3240
- .ap-federation__actions-row {
3241
- display: flex;
3242
- flex-wrap: wrap;
3243
- gap: var(--space-s);
3244
- align-items: center;
3245
- }
3246
-
3247
- .ap-federation__result {
3248
- margin-block-start: var(--space-xs);
3249
- color: var(--color-green50);
3250
- font-size: var(--font-size-s);
3251
- }
3252
-
3253
- .ap-federation__error {
3254
- margin-block-start: var(--space-xs);
3255
- color: var(--color-red45);
3256
- font-size: var(--font-size-s);
3257
- }
3258
-
3259
- .ap-federation__lookup-form {
3260
- display: flex;
3261
- gap: var(--space-s);
3262
- }
3263
-
3264
- .ap-federation__lookup-input {
3265
- flex: 1;
3266
- min-width: 0;
3267
- padding: 0.5rem 0.75rem;
3268
- border: var(--border-width-thin) solid var(--color-outline);
3269
- border-radius: var(--border-radius-small);
3270
- font: inherit;
3271
- color: var(--color-on-background);
3272
- background: var(--color-background);
3273
- }
3274
-
3275
- .ap-federation__json-view {
3276
- margin-block-start: var(--space-s);
3277
- padding: var(--space-m);
3278
- background: var(--color-offset);
3279
- border-radius: var(--border-radius-small);
3280
- font-family: monospace;
3281
- font-size: var(--font-size-s);
3282
- color: var(--color-on-background);
3283
- max-height: 24rem;
3284
- overflow: auto;
3285
- white-space: pre-wrap;
3286
- word-break: break-word;
3287
- }
3288
-
3289
- .ap-federation__posts-list {
3290
- display: flex;
3291
- flex-direction: column;
3292
- gap: var(--space-xs);
3293
- }
3294
-
3295
- .ap-federation__post-row {
3296
- display: flex;
3297
- justify-content: space-between;
3298
- align-items: center;
3299
- gap: var(--space-m);
3300
- padding: var(--space-s);
3301
- background: var(--color-offset);
3302
- border-radius: var(--border-radius-small);
3303
- }
3304
-
3305
- .ap-federation__post-info {
3306
- display: flex;
3307
- flex-direction: column;
3308
- gap: var(--space-xs);
3309
- min-width: 0;
3310
- }
3311
-
3312
- .ap-federation__post-title {
3313
- font-weight: 500;
3314
- white-space: nowrap;
3315
- overflow: hidden;
3316
- text-overflow: ellipsis;
3317
- }
3318
-
3319
- .ap-federation__post-meta {
3320
- display: flex;
3321
- align-items: center;
3322
- gap: var(--space-xs);
3323
- font-size: var(--font-size-s);
3324
- color: var(--color-on-offset);
3325
- }
3326
-
3327
- .ap-federation__post-actions {
3328
- display: flex;
3329
- gap: var(--space-xs);
3330
- flex-shrink: 0;
3331
- }
3332
-
3333
- .ap-federation__post-btn {
3334
- padding: var(--space-xs) var(--space-s);
3335
- font-size: var(--font-size-s);
3336
- border: var(--border-width-thin) solid var(--color-outline);
3337
- border-radius: var(--border-radius-small);
3338
- background: var(--color-background);
3339
- color: var(--color-on-background);
3340
- cursor: pointer;
3341
- }
3342
-
3343
- .ap-federation__post-btn:hover {
3344
- background: var(--color-offset);
3345
- }
3346
-
3347
- .ap-federation__post-btn--danger {
3348
- color: var(--color-red45);
3349
- border-color: var(--color-red45);
3350
- }
3351
-
3352
- .ap-federation__post-btn--danger:hover {
3353
- background: color-mix(in srgb, var(--color-red45) 10%, transparent);
3354
- }
3355
-
3356
- .ap-federation__modal-overlay {
3357
- position: fixed;
3358
- inset: 0;
3359
- z-index: 1000;
3360
- display: flex;
3361
- align-items: center;
3362
- justify-content: center;
3363
- background: hsl(var(--tint-neutral) 10% / 0.5);
3364
- }
3365
-
3366
- .ap-federation__modal {
3367
- width: min(90vw, 48rem);
3368
- max-height: 80vh;
3369
- display: flex;
3370
- flex-direction: column;
3371
- background: var(--color-background);
3372
- border-radius: var(--border-radius-small);
3373
- box-shadow: 0 4px 24px hsl(var(--tint-neutral) 10% / 0.2);
3374
- }
3375
-
3376
- .ap-federation__modal-header {
3377
- display: flex;
3378
- justify-content: space-between;
3379
- align-items: center;
3380
- padding: var(--space-s) var(--space-m);
3381
- border-block-end: var(--border-width-thin) solid var(--color-outline);
3382
- }
3383
-
3384
- .ap-federation__modal-header h3 {
3385
- margin: 0;
3386
- font-size: var(--font-size-m);
3387
- }
3388
-
3389
- .ap-federation__modal-close {
3390
- font-size: var(--font-size-xl);
3391
- line-height: 1;
3392
- padding: 0 var(--space-xs);
3393
- border: none;
3394
- background: none;
3395
- color: var(--color-on-offset);
3396
- cursor: pointer;
3397
- }
3398
-
3399
- .ap-federation__modal .ap-federation__json-view {
3400
- margin: 0;
3401
- border-radius: 0 0 var(--border-radius-small) var(--border-radius-small);
3402
- flex: 1;
3403
- overflow: auto;
3404
- }
3405
-
3406
- @media (max-width: 40rem) {
3407
- .ap-federation__post-row {
3408
- flex-direction: column;
3409
- align-items: flex-start;
3410
- }
3411
-
3412
- .ap-federation__lookup-form {
3413
- flex-direction: column;
3414
- }
3415
- }
3416
-
3417
- /* Follow request approve/reject actions */
3418
- .ap-follow-request {
3419
- margin-block-end: var(--space-m);
3420
- }
3421
-
3422
- .ap-follow-request__actions {
3423
- display: flex;
3424
- gap: var(--space-s);
3425
- margin-block-start: var(--space-xs);
3426
- padding-inline-start: var(--space-l);
3427
- }
3428
-
3429
- .ap-follow-request__form {
3430
- display: inline;
3431
- }
3432
-
3433
- .button--danger {
3434
- background-color: var(--color-red45);
3435
- color: white;
3436
- }
3437
-
3438
- .button--danger:hover {
3439
- background-color: var(--color-red35, #c0392b);
3440
- }
3441
-
8
+ @import url("css/base.css");
9
+ @import url("css/card.css");
10
+ @import url("css/media.css");
11
+ @import url("css/interactions.css");
12
+ @import url("css/compose.css");
13
+ @import url("css/notifications.css");
14
+ @import url("css/messages.css");
15
+ @import url("css/profile.css");
16
+ @import url("css/moderation.css");
17
+ @import url("css/skeleton.css");
18
+ @import url("css/responsive.css");
19
+ @import url("css/features.css");
20
+ @import url("css/explore.css");
21
+ @import url("css/dark-mode.css");
22
+ @import url("css/federation.css");