source: Klonkt/src/views/partials/shared-styles.ejs@ 3a3a882

main
Last change on this file since 3a3a882 was 3a3a882, checked in by Robin <roboburr@…>, 3 weeks ago

Lezen staat in de cirkel zichtbaar maar dood, in plaats van weg

De knop verdween daar helemaal, met het argument dat een knop die niets
doet erger is dan geen knop. In de praktijk pakte dat andersom uit: de
pil werd smaller op de cirkel en breder op solo, en die sprong leest als
'er is hier iets weg' -- terwijl juist NIET duidelijk werd dat Lezen
bestaat en er alleen hier niet kan. Nu staat hij er grijs bij, met een
titel die zegt waarom, en is Grid zichtbaar de enige mogelijkheid.

Wat daarmee vervalt: de aparte cirkel-voorkeur ('pcms-cirkel-view').
Die kon nog maar een waarde hebben. De solo-keuze blijft onaangeroerd --
op de cirkel schrijven we niets meer naar localStorage, dus je komt thuis
in de weergave die je achterliet.

Drie plekken rekenden erop dat de knop er niet was en zijn meegegaan: de
terugval 'is dit de enige knop, dan brengt hij je naar de standaard' (er
zijn er nu twee, en op de cirkel hoort Grid juist de enige te blijven),
de aria-sync (een dode knop kan nooit de actieve zijn) en de klik-
afhandeling (expliciet op sw.disabled, niet vertrouwen op dat een
disabled button geen click vuurt -- deze listener hangt op document).

Co-Authored-By: Claude Opus 5 <noreply@…>

  • Property mode set to 100644
File size: 13.6 KB
Line 
1<style>
2/* ─────────────────────────────────────────────────
3 View switcher (timeline ↔ grid + grid-cols picker)
4 ───────────────────────────────────────────────── */
5.view-switcher-wrap {
6 border-bottom: 1px solid var(--rule);
7 background: var(--paper);
8 /* No extra margin-top: this centres the pill between the profile-header
9 rule (above) and the own border (below). Equal space above/below the
10 pill comes from the symmetric container padding below. The margin-bottom
11 (1.5rem in style.css) keeps breathing room toward the feed. */
12 margin-top: 0;
13}
14.view-switcher-wrap .container {
15 display: flex; align-items: center; justify-content: center; gap: 0.75rem;
16 /* Symmetric padding → equal space above and below the pill (≈8px),
17 centred between the two dividing lines. */
18 padding: 0.5rem 1rem;
19 max-width: 1200px; margin: 0 auto;
20 flex-wrap: wrap;
21}
22.view-switcher {
23 display: inline-flex;
24 background: var(--paper-2);
25 border: 1px solid var(--rule);
26 border-radius: 999px;
27 padding: 0.15rem;
28}
29.view-switch-btn {
30 display: inline-flex; align-items: center; gap: 0.35rem;
31 padding: 0.35rem 0.85rem;
32 border: 0; background: transparent; color: var(--ink-muted, var(--ink-soft));
33 cursor: pointer; border-radius: 999px;
34 font-size: 0.85rem; font-family: inherit;
35 transition: background 120ms, color 120ms;
36}
37.view-switch-btn:hover { color: var(--ink); }
38/* Active = white (light background, dark text). Via aria-selected (element
39 attribute, set by syncAria + on htmx:afterSettle) → htmx-robust. On non-
40 feed pages syncAria sets aria-selected=false → both grey. */
41.view-switch-btn[aria-selected="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
42/* Lezen in de cirkel: zichtbaar maar dood. Niet weggelaten, want dan springt de
43 pil van breedte tussen Solo en Cirkel, en juist DAT verbergt dat er een
44 tweede weergave bestaat. Grijs + not-allowed zegt "bestaat, kan hier niet". */
45.view-switch-btn[disabled] { opacity: .38; cursor: not-allowed; }
46.view-switch-btn[disabled]:hover { color: var(--ink-muted, var(--ink-soft)); background: transparent; }
47
48/* Agenda = its OWN pill (separate from Timeline/Grid, so the feed-toggle is never
49 disturbed). Same look as the view-switcher pill. Visible in all modes. */
50.agenda-pill { display: inline-flex; align-items: center; } /* no box — standalone icon+text link */
51.vs-agenda {
52 display: inline-flex; align-items: center; gap: 0.4rem;
53 padding: 0.35rem 0.5rem;
54 color: var(--ink-muted, var(--ink-soft));
55 text-decoration: none;
56 font-size: 0.9rem; font-family: inherit;
57 transition: color 120ms;
58}
59.vs-agenda:hover { color: var(--ink); }
60/* Active (on the agenda page) = bright/white. Element-class (in the OOB-rendered
61 chrome) rather than body-class CSS → stays reliable after htmx navigation. */
62.vs-agenda.is-active { color: var(--ink); font-weight: 600; }
63
64/* Mobile: Agenda on its own row at the top, Solo/Circle + Timeline/Grid together
65 on the row below (together ~330px → fits within a phone, instead of the old
66 unbalanced split Agenda+Solo / Timeline). */
67@media (max-width: 520px) {
68 .view-switcher-wrap .agenda-pill { flex: 0 0 100%; justify-content: center; }
69}
70
71.grid-cols-picker {
72 display: none; /* desktop-only, see media query */
73 gap: 0.2rem;
74}
75.grid-cols-btn {
76 width: 28px; height: 28px;
77 border: 1px solid var(--rule);
78 background: var(--paper-2);
79 color: var(--ink-muted, var(--ink-soft));
80 border-radius: 4px;
81 font-size: 0.8rem; font-weight: 600;
82 cursor: pointer;
83 font-variant-numeric: tabular-nums;
84}
85.grid-cols-btn:hover { color: var(--ink); border-color: var(--accent); }
86.grid-cols-btn.is-active { background: var(--accent); color: white; border-color: var(--accent); }
87
88/* Show grid-cols picker only on grid view + desktop */
89@media (min-width: 720px) {
90 body[data-feed-view="grid"] .grid-cols-picker { display: inline-flex; }
91}
92
93/* Switcher is hidden only on admin pages — admin has a dedicated layout
94 and its own back-button flow where Tijdlijn/Grid is irrelevant. On
95 every other page (home, post, tag, archive, search, account) it stays
96 visible so the user keeps a consistent return-to-feed control. */
97.on-admin .view-switcher-wrap { display: none; }
98
99/* On a standalone post there is no feed to switch, so no button should look "active"
100 (coloured). The active state lives in style.css on body[data-feed-view]
101 / body[data-grid-cols] (background:var(--ink)); we override that MORE SPECIFICALLY
102 via body.on-post so the buttons become neutral/grey — but remain clickable
103 (the click-handler then navigates to the feed in that view). The
104 body-class switches client-side on HTMX-nav, so this works without a reload too. */
105body.on-post[data-feed-view="reader"] .view-switch-btn[data-view="reader"],
106body.on-post[data-feed-view="grid"] .view-switch-btn[data-view="grid"],
107body.on-post[data-grid-cols="2"] .grid-cols-btn[data-cols="2"],
108body.on-post[data-grid-cols="3"] .grid-cols-btn[data-cols="3"],
109body.on-post[data-grid-cols="4"] .grid-cols-btn[data-cols="4"] {
110 background: transparent;
111 color: var(--ink-muted, var(--ink-soft));
112 border-color: var(--rule);
113}
114
115
116/* Spacing between switcher-bar and the page content below.
117 .feed-timeline (used on home + archive + post-list pages) gets a top
118 margin so the first post doesn't collide with the switcher's border.
119 .feed-grid already has its own top spacing from grid-tile padding. */
120.view-switcher-wrap + #pcms-main .feed-timeline,
121.view-switcher-wrap + #pcms-main .container:first-child {
122 margin-top: 1.5rem;
123}
124
125/* Feed layout switching is in the v9 style.css (style.css):
126 .feed-timeline always rendered, .feed-grid hidden unless on-home + grid-mode. */
127
128/* ─────────────────────────────────────────────────
129 PWA install button (lives in topnav, hidden by default)
130 ───────────────────────────────────────────────── */
131#pwa-install-btn { color: var(--accent); }
132#pwa-install-btn:hover { background: var(--paper-2); }
133
134/* Shared button + form styles (used across pages) */
135.btn {
136 display: inline-flex;
137 align-items: center;
138 gap: 0.4rem;
139 padding: 0.55rem 1rem;
140 border: 1px solid var(--rule);
141 background: var(--paper-2);
142 color: var(--ink);
143 font-family: var(--font-ui, system-ui), sans-serif;
144 font-size: 0.9rem;
145 font-weight: 500;
146 text-decoration: none;
147 border-radius: 5px;
148 cursor: pointer;
149 transition: background 150ms, border-color 150ms;
150}
151.btn:hover { border-color: var(--accent); }
152.btn-primary { background: var(--accent); color: white; border-color: var(--accent); }
153.btn-primary:hover { opacity: 0.92; border-color: var(--accent); }
154.btn-success { background: #16a34a; color: white; border-color: #16a34a; }
155.btn-danger { background: #dc2626; color: white; border-color: #dc2626; }
156
157.alert { padding: 0.75rem 1rem; border-radius: 5px; margin-bottom: 1rem; }
158.alert-error { background: #fee2e2; color: #991b1b; border: 1px solid #fecaca; }
159.alert-success { background: #d1fae5; color: #065f46; border: 1px solid #a7f3d0; }
160
161.auth-page { max-width: 420px; margin: 3rem auto; padding: 0 1rem; }
162.auth-page h1 { font-family: var(--font-display, serif); text-align: center; margin: 0 0 1.5rem; }
163.auth-form { display: flex; flex-direction: column; gap: 1rem; }
164.auth-form label { display: flex; flex-direction: column; gap: 0.3rem; }
165.auth-form label > span { font-size: 0.85rem; font-weight: 600; color: var(--ink-soft); }
166.auth-form input { padding: 0.6rem 0.75rem; border: 1px solid var(--rule); border-radius: 4px; background: var(--paper); color: var(--ink); font-size: 1rem; }
167.auth-form .btn { justify-content: center; padding: 0.7rem; font-size: 1rem; margin-top: 0.5rem; }
168.auth-link { text-align: center; color: var(--ink-muted); font-size: 0.9rem; margin: 1rem 0 0; }
169.auth-link a { color: var(--accent); }
170.auth-intro { text-align: center; color: var(--ink-muted); font-size: 0.95rem; margin: 0 0 1rem; }
171.auth-divider { display: flex; align-items: center; gap: 0.75rem; margin: 1.25rem 0; color: var(--ink-muted); font-size: 0.85rem; }
172.auth-divider::before, .auth-divider::after { content: ''; flex: 1; height: 1px; background: var(--rule); }
173
174/* HTMX loading indicator */
175.pcms-loading {
176 display: none;
177 position: fixed;
178 top: 60px;
179 right: 1rem;
180 width: 24px;
181 height: 24px;
182 border: 3px solid var(--paper-2);
183 border-top-color: var(--accent);
184 border-radius: 50%;
185 animation: spin 0.8s linear infinite;
186 z-index: 1000;
187}
188.htmx-request .pcms-loading { display: block; }
189@keyframes spin { to { transform: rotate(360deg); } }
190
191/* Load more (Solo, Cirkel, News, Messages) — page size 72, htmx append. */
192.load-more-wrap { display: flex; justify-content: center; margin: 1.5rem 0 .5rem; }
193.load-more-wrap:empty { margin: 0; }
194.load-more-btn { padding: .6rem 1.4rem; border-radius: 999px; cursor: pointer;
195 font: inherit; font-weight: 600; color: var(--ink, inherit);
196 background: color-mix(in srgb, var(--ink, #000) 5%, transparent);
197 border: 1px solid color-mix(in srgb, var(--ink, #000) 14%, transparent); }
198.load-more-btn:hover { background: color-mix(in srgb, var(--ink, #000) 9%, transparent); }
199.load-more-btn.htmx-request { opacity: .6; pointer-events: none; }
200
201/* FEP-9098 custom emojis: small inline images (Shaer parity), rendered in note
202 content and display names across the timeline, messages and threads. Never
203 styled as media (no rounding/background), and never blown up to media width. */
204img.emoji { height: 1.3em; width: auto; margin: 0 .05em; vertical-align: -0.2em;
205 display: inline-block; border-radius: 0; background: none; box-shadow: none; }
206.tl-content img.emoji, .tl-quote-body img.emoji, .msg-content img.emoji, .comment-content img.emoji,
207.tl-author img.emoji, .tl-boost-by img.emoji, .tl-quote-name img.emoji, .msg-who img.emoji, .comment-author img.emoji {
208 max-width: none; height: 1.3em; border-radius: 0; background: none; box-shadow: none; vertical-align: -0.2em; }
209
210/* ── The body of a post ────────────────────────────────────────────────────
211 Shared with partials/note-body.ejs, so a post looks the same in de Krant, in
212 Berichten and in the Guardian PWA. These used to live in the Krant's own
213 <style> block, which is why a post outside de Krant came out unstyled.
214 Krant-only behaviour (the clamp + "read more", the poll, the action bar)
215 stays in pages/news.ejs. */
216.tl-content { line-height: 1.55; overflow-wrap: anywhere; }
217.tl-content p { margin: .4rem 0; } .tl-content p:first-child { margin-top: 0; } .tl-content p:last-child { margin-bottom: 0; }
218.tl-content a { color: var(--accent, #06c); }
219.tl-content img { max-width: 100%; height: auto; border-radius: 10px; background: #fff; }
220
221/* FEP-044f embedded quote card (mirror of the Shaer QuoteCard). Also carries
222 an external link preview: same card, different origin. */
223.tl-quote { margin: .75rem 0 0; padding: .6rem .7rem; border-radius: 12px;
224 border: 1px solid color-mix(in srgb, var(--ink, #000) 12%, transparent);
225 background: color-mix(in srgb, var(--ink, #000) 3.5%, transparent); }
226.tl-quote-head { display: flex; align-items: center; gap: .4rem; margin: 0 0 .35rem; min-width: 0; }
227.tl-quote-avatar { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; object-fit: cover; background: #fff; }
228.tl-quote-name { font-weight: 700; font-size: .85rem; color: var(--ink, inherit); white-space: nowrap; }
229.tl-quote-handle { color: var(--ink-soft, #888); font-size: .78rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
230.tl-quote-body { line-height: 1.5; font-size: .92rem; color: var(--ink-soft, #555);
231 overflow-wrap: anywhere; max-height: 16em; overflow: hidden; }
232.tl-quote-body p { margin: .3rem 0; } .tl-quote-body p:first-child { margin-top: 0; } .tl-quote-body p:last-child { margin-bottom: 0; }
233.tl-quote-body a { color: var(--accent, #06c); }
234.tl-quote-media { display: block; margin: .45rem 0 0; }
235.tl-quote-media img { max-width: 100%; height: auto; border-radius: 8px; }
236
237/* Always show the FULL image at its natural ratio — never cropped, no letterbox. */
238.tl-media { display: flex; flex-direction: column; gap: .4rem; margin: .75rem 0 0; }
239.tl-media-img { display: block; border-radius: 12px; overflow: hidden;
240 background-image: linear-gradient(135deg,
241 color-mix(in srgb, var(--accent, #888) 22%, var(--paper-2, var(--paper))) 0%,
242 color-mix(in srgb, var(--accent, #888) 6%, var(--paper-2, var(--paper))) 100%); }
243.tl-media-img img { width: 100%; height: auto; display: block; background: #fff; transition: opacity .4s ease; }
244.tl-media-img img.is-loading { opacity: 0; }
245/* Reserve placeholder space while the (natural-aspect) feed image loads. */
246.tl-media-img:has(img.is-loading) { min-height: 220px; }
247.tl-media-video, .tl-media-audio { width: 100%; margin: .75rem 0 0; border-radius: 12px; display: block; }
248.tl-media-video { max-height: 480px; background: #000; }
249
250/* In Berichten a post sits inside a notification row, so it starts tighter and
251 its media stays modest: the row is a pointer to the post, not the post page. */
252.msg-note .tl-content { line-height: 1.5; }
253.msg-note .tl-quote, .msg-note .tl-media, .msg-note .tl-media-video, .msg-note .tl-media-audio { margin-top: .5rem; }
254.msg-note .tl-media-img:has(img.is-loading) { min-height: 120px; }
255.msg-note .tl-media-video { max-height: 320px; }
256</style>
Note: See TracBrowser for help on using the repository browser.