gs4f2wcln: Fit long text-only posts to the slide and add Read more and more/less for long post text on mobile

This commit is contained in:
2026-10-20 10:12:01 -06:00
parent d653e8e75d
commit 6af225afa5
6 changed files with 477 additions and 28 deletions
+135 -14
View File
@@ -24,6 +24,8 @@
scrollbar-width: none;
}
.reel::-webkit-scrollbar { display: none; }
/* Long text is open on the slide on screen: the reel holds still, swipes scroll the text. */
.reel[data-locked="true"] { overflow-y: hidden; }
.slide {
--slide-text-bg: radial-gradient(120% 70% at 0% 0%, var(--accent-soft), transparent 62%), var(--bg);
@@ -154,14 +156,35 @@
.slide-error { margin: 0; color: var(--danger); font-size: 13px; font-weight: 600; }
.slide-on-media .slide-error { color: var(--on-media); }
/* Text-only post: the text is the hero, a serif quote with a crimson opening mark. */
.slide-quote-w { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.slide-quote {
/* Text-only post: the text is the hero, a serif quote with a crimson opening mark.
The box spans from under the top bar (or the own-post menu) to above the author
block; SlideText steps the size 31 → 26 → 22 → 19px until the text fits. */
.slide-quote-w {
position: absolute;
top: calc(72px + env(safe-area-inset-top, 0px));
bottom: 181px; /* .slide-meta bottom (108px) + the author block (53px) + 20px */
left: 24px;
right: 28px;
top: 46%;
transform: translateY(-50%);
z-index: 2;
display: flex;
flex-direction: column;
overflow: hidden;
pointer-events: none;
}
.slide-own .slide-quote-w { top: calc(122px + env(safe-area-inset-top, 0px)); }
/* Auto margins center the quote and, unlike justify-content, never push overflow above the box. */
.slide-quote-in { margin: auto 0; }
.slide-quote-w.is-clamped .slide-quote-in { margin-top: 0; }
.slide-quote-mark {
display: block;
margin-bottom: 6px;
color: var(--accent);
font-family: var(--font-serif), Georgia, serif;
font-size: 84px;
font-weight: 600;
line-height: .62;
}
.slide-quote {
margin: 0;
font-family: var(--font-serif), Georgia, serif;
font-size: 31px;
@@ -169,19 +192,114 @@
line-height: 1.2;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.slide-quote.is-clamped {
display: -webkit-box;
-webkit-line-clamp: 8;
-webkit-box-orient: vertical;
overflow: hidden;
}
.slide-quote::before {
content: "\201C";
display: block;
margin-bottom: 6px;
color: var(--accent);
font-size: 84px;
line-height: .62;
/* "Read more", "Close", "more" and "less": real buttons, 44px tall to tap. */
.slide-more {
appearance: none;
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 44px;
margin: 0;
padding: 0 18px;
border: 0;
border-radius: 14px;
font: inherit;
font-size: 14px;
font-weight: 700;
letter-spacing: .01em;
color: var(--ink);
background: var(--glass);
-webkit-backdrop-filter: blur(16px) saturate(1.6);
backdrop-filter: blur(16px) saturate(1.6);
box-shadow: inset 0 0 0 1px var(--line);
cursor: pointer;
pointer-events: auto;
transition: transform .15s;
}
.slide-more:active { transform: scale(.96); }
.slide-more:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.slide-more-quote { position: absolute; left: 0; bottom: 0; }
/* The full text of a long text-only post, over the slide between the top bar and the dock. */
@keyframes slide-reader-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.slide-reader {
position: absolute;
top: calc(64px + env(safe-area-inset-top, 0px));
bottom: calc(88px + env(safe-area-inset-bottom, 0px));
left: 12px;
right: 12px;
z-index: 7;
display: flex;
flex-direction: column;
gap: 10px;
padding: 20px 14px 14px 20px;
border-radius: 22px;
color: var(--ink);
background: var(--bg);
box-shadow: var(--shadow-pop), inset 0 0 0 1px var(--line);
animation: slide-reader-in .28s var(--ease) both;
}
.slide-reader-scroll {
flex: 1;
min-height: 0;
overflow-y: auto;
overscroll-behavior: contain;
padding-right: 6px;
}
.slide-reader-scroll:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 6px; }
.slide-reader-text {
margin: 0;
font-family: var(--font-serif), Georgia, serif;
font-size: 22px;
font-weight: 600;
line-height: 1.35;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.slide-reader-close { flex: none; align-self: flex-end; }
/* Caption "more" / "less": a text button right under the three-line clamp. */
.slide-more.slide-more-caption {
align-self: flex-start;
flex: none;
margin: -12px 0 -10px -6px;
padding: 0 6px;
min-width: 44px;
background: none;
-webkit-backdrop-filter: none;
backdrop-filter: none;
box-shadow: none;
color: inherit;
text-decoration: underline;
text-underline-offset: 3px;
text-shadow: 0 1px 12px var(--media-shadow);
}
/* Open caption: the full text over the media on a darker scrim, scrolling inside the slide. */
.slide-who,
.slide-error { flex: none; }
.slide-text-open .slide-meta {
top: calc(122px + env(safe-area-inset-top, 0px));
justify-content: flex-end;
}
.slide-text.is-open {
display: block;
-webkit-line-clamp: unset;
flex: 0 1 auto;
min-height: 0;
overflow-y: auto;
overscroll-behavior: contain;
animation: slide-reader-in .28s var(--ease) both;
}
.slide-text.is-open:focus-visible { outline: 2px solid var(--on-media); outline-offset: 4px; }
.slide-text-open .slide-scrim { height: 100%; background: var(--media-scrim); }
.slide-text-open .slide-scrim-top { opacity: 0; }
/* The slide on screen: its content rises in when it snaps into place. */
.is-cur .slide-meta,
@@ -391,10 +509,13 @@
.is-cur .slide-quote-w,
.slide-skel i,
.slide-burst,
.slide-reader,
.slide-text.is-open,
.slide-hint svg,
.reel-pill,
.dk-beat svg { animation: none !important; }
.slide-art { transition: none !important; }
.slide-art,
.slide-more { transition: none !important; }
}
/* Top bar (spec "Top bar"): frosted pills over the feed. Over a media slide they use a