v3: fixed roles propagation bug, fixed inconsistent file drop zone, fixed chat attachments wrongfully pruned, some visual tweaks
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 41s

This commit is contained in:
2026-06-30 13:41:36 +02:00
parent d2d086831e
commit 7773a8a501
12 changed files with 317 additions and 237 deletions

View File

@@ -40,7 +40,8 @@
border: none;
padding: 0;
}
.md ul, .md ol {
.md ul,
.md ol {
padding-left: 1.5em;
margin: 0.4em 0;
}
@@ -53,7 +54,12 @@
padding: 0.2em 0.75em;
opacity: 0.75;
}
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6 {
.md h1,
.md h2,
.md h3,
.md h4,
.md h5,
.md h6 {
margin: 0.6em 0 0.2em;
font-weight: 700;
line-height: 1.25;
@@ -466,17 +472,6 @@
}
/* ── FileDropZone ── */
.fdz-wrapper {
display: flex;
flex-direction: column;
gap: 0.4rem;
}
.fdz-label {
font-size: 0.9rem;
font-weight: 500;
}
.fdz {
border: 2px dashed var(--color-border-subtle);
border-radius: 10px;
@@ -1092,13 +1087,16 @@ body.has-player {
edge. The lane width is `--fab-lane` (860px for most feeds; the journal
grid is wider, see below). Falls back to a 1.25rem viewport gutter once
that margin is too narrow to hold the button. */
right: max(1.25rem, calc(50% - var(--fab-lane, 860px) / 2 - var(--fab-size) - 1rem));
right: max(1.25rem, calc(50% - var(--fab-lane, 860px) / 2 - var(--fab-size) -
1rem));
/* Anchored to the bottom-right by default, but expressed via `top` (rather
than `bottom`) so the jump to the top-right when a player mounts can
animate as a slide. `dvh` tracks the visible viewport on mobile; `vh` is
the fallback for browsers without it. */
top: calc(100vh - var(--fab-size) - 1.25rem - env(safe-area-inset-bottom, 0px));
top: calc(100dvh - var(--fab-size) - 1.25rem - env(safe-area-inset-bottom, 0px));
top: calc(100vh - var(--fab-size) - 1.25rem - env(safe-area-inset-bottom,
0px));
top: calc(100dvh - var(--fab-size) - 1.25rem - env(safe-area-inset-bottom,
0px));
z-index: 900;
width: var(--fab-size);
height: var(--fab-size);
@@ -1112,7 +1110,8 @@ body.has-player {
background: var(--color-accent);
color: var(--color-on-accent);
cursor: pointer;
box-shadow: 0 4px 16px color-mix(in srgb, var(--color-accent) 45%, transparent),
box-shadow: 0 4px 16px color-mix(in srgb, var(--color-accent) 45%,
transparent),
0 2px 6px rgba(0, 0, 0, 0.3);
/* Hidden state: faded out, nudged down, non-interactive. */
opacity: 0;
@@ -1136,7 +1135,8 @@ body.has-player {
.dump-fab:hover {
background: var(--color-accent-hover);
transform: translateY(-2px) scale(1);
box-shadow: 0 6px 20px color-mix(in srgb, var(--color-accent) 55%, transparent),
box-shadow: 0 6px 20px color-mix(in srgb, var(--color-accent) 55%,
transparent),
0 2px 6px rgba(0, 0, 0, 0.3);
}
@@ -1169,10 +1169,13 @@ body.has-fab .page-content {
position: fixed;
--fab-size: 3.5rem;
/* Share the dump-fab's column. */
right: max(1.25rem, calc(50% - var(--fab-lane, 860px) / 2 - var(--fab-size) - 1rem));
right: max(1.25rem, calc(50% - var(--fab-lane, 860px) / 2 - var(--fab-size) -
1rem));
/* One button-height + gap above the dump-fab's bottom-anchored resting spot. */
top: calc(100vh - var(--fab-size) * 2 - 2rem - env(safe-area-inset-bottom, 0px));
top: calc(100dvh - var(--fab-size) * 2 - 2rem - env(safe-area-inset-bottom, 0px));
top: calc(100vh - var(--fab-size) * 2 - 2rem - env(safe-area-inset-bottom,
0px));
top: calc(100dvh - var(--fab-size) * 2 - 2rem - env(safe-area-inset-bottom,
0px));
z-index: 900;
width: var(--fab-size);
height: var(--fab-size);
@@ -1185,7 +1188,8 @@ body.has-fab .page-content {
background: var(--color-accent);
color: var(--color-on-accent);
cursor: pointer;
box-shadow: 0 4px 16px color-mix(in srgb, var(--color-accent) 45%, transparent),
box-shadow: 0 4px 16px color-mix(in srgb, var(--color-accent) 45%,
transparent),
0 2px 6px rgba(0, 0, 0, 0.3);
opacity: 0;
transform: translateY(1rem) scale(0.9);
@@ -1208,7 +1212,8 @@ body.has-fab .page-content {
.chat-fab:hover {
background: var(--color-accent-hover);
transform: translateY(-2px) scale(1);
box-shadow: 0 6px 20px color-mix(in srgb, var(--color-accent) 55%, transparent),
box-shadow: 0 6px 20px color-mix(in srgb, var(--color-accent) 55%,
transparent),
0 2px 6px rgba(0, 0, 0, 0.3);
}
@@ -1220,8 +1225,10 @@ body.has-fab .page-content {
body.has-player .chat-fab {
top: calc(1.25rem + env(safe-area-inset-top, 0px));
/* Stack below the dump-fab in the top-right corner to avoid overlap. */
right: max(1.25rem, calc(50% - var(--fab-lane, 860px) / 2 - var(--fab-size) - 1rem));
top: calc(1.25rem + var(--fab-size) + 0.75rem + env(safe-area-inset-top, 0px));
right: max(1.25rem, calc(50% - var(--fab-lane, 860px) / 2 - var(--fab-size) -
1rem));
top: calc(1.25rem + var(--fab-size) + 0.75rem + env(safe-area-inset-top,
0px));
}
/* The badge sits on the circular FAB; nudge it onto the rim. */
@@ -2990,7 +2997,8 @@ body.has-player .chat-fab {
.dump-card-inner:hover .dump-card-preview,
.playlist-card-inner:hover .playlist-card-preview {
transform: scale(1.08);
box-shadow: inset 0 0 0 1px var(--color-border), 0 4px 12px rgba(0, 0, 0, 0.25);
box-shadow: inset 0 0 0 1px var(--color-border), 0 4px 12px rgba(0, 0, 0,
0.25);
}
/* ── Shared card preview icon ── */
@@ -3681,7 +3689,9 @@ body.has-player .chat-fab {
}
@keyframes chat-typing-bounce {
0%, 60%, 100% {
0%,
60%,
100% {
opacity: 0.3;
transform: translateY(0);
}
@@ -3825,7 +3835,6 @@ body.has-player .chat-fab {
background: color-mix(in srgb, var(--color-accent) 8%, transparent);
}
/* ── Playlist detail page ── */
.playlist-detail-header {
background: var(--color-surface);
@@ -4092,6 +4101,60 @@ body.has-player .chat-fab {
letter-spacing: 0.08em;
}
/* Backlinks are supporting context, not the main event — render them as a
tighter, lighter list so they stay scannable but clearly subordinate to
the dump's own content. */
.related-section .related-section-title {
margin-bottom: 0.85rem;
}
.related-section .dump-feed {
padding: 0;
gap: 0.4rem;
max-width: none;
}
.related-section .dump-card {
border-width: 1px;
border-radius: 8px;
background: transparent;
opacity: 0.78;
transition: border-color 0.15s, opacity 0.15s;
}
.related-section .dump-card:hover {
opacity: 1;
}
.related-section .dump-card-inner {
padding: 0.45rem 0.65rem;
gap: 0.6rem;
}
.related-section .dump-card-preview {
width: 76px;
height: 43px;
align-self: center;
}
.related-section .dump-card-title {
font-size: 0.88rem;
}
/* Keep just enough description to orient, but only a single muted line. */
.related-section .dump-card-comment {
font-size: 0.78rem;
-webkit-line-clamp: 1;
line-clamp: 1;
}
@media (max-width: 512px) {
.related-section .dump-card-preview {
width: 64px;
height: 36px;
}
}
.comment-list {
list-style: none;
margin: 0;