source: Klonkt/src/assets/css/style.css@ 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: 153.7 KB
Line 
1/* ============================================================
2 LOKALE FONTS — SIL OFL 1.1 licensed, self-hosted
3 Geen third-party requests, geen privacy-leak naar Google.
4 Variable WOFF2 bestanden onder /assets/fonts/
5 Licenses in /assets/fonts/licenses/
6 ============================================================ */
7@font-face {
8 font-family: 'Fraunces';
9 font-style: normal;
10 font-display: swap;
11 font-weight: 100 900;
12 src: url('/assets/fonts/fraunces-latin-full-normal.woff2') format('woff2-variations');
13 unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
14}
15@font-face {
16 font-family: 'Fraunces';
17 font-style: italic;
18 font-display: swap;
19 font-weight: 100 900;
20 src: url('/assets/fonts/fraunces-latin-full-italic.woff2') format('woff2-variations');
21 unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
22}
23@font-face {
24 font-family: 'Literata';
25 font-style: normal;
26 font-display: swap;
27 font-weight: 400 700;
28 src: url('/assets/fonts/literata-latin-opsz-normal.woff2') format('woff2-variations');
29 unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
30}
31@font-face {
32 font-family: 'Literata';
33 font-style: italic;
34 font-display: swap;
35 font-weight: 400 700;
36 src: url('/assets/fonts/literata-latin-opsz-italic.woff2') format('woff2-variations');
37 unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
38}
39@font-face {
40 font-family: 'Plus Jakarta Sans';
41 font-style: normal;
42 font-display: swap;
43 font-weight: 400 700;
44 src: url('/assets/fonts/plus-jakarta-sans-latin-wght-normal.woff2') format('woff2-variations');
45 unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
46}
47@font-face {
48 font-family: 'Plus Jakarta Sans';
49 font-style: italic;
50 font-display: swap;
51 font-weight: 400 700;
52 src: url('/assets/fonts/plus-jakarta-sans-latin-wght-italic.woff2') format('woff2-variations');
53 unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
54}
55
56/* Klonkt publieke stijl — editorial-ish, geen emoji-UI */
57
58:root {
59 --font-display: 'Fraunces', Georgia, serif;
60 --font-body: 'Literata', Georgia, serif;
61 --font-ui: 'Plus Jakarta Sans', system-ui, sans-serif;
62 --font-mono: ui-monospace, Menlo, Consolas, monospace;
63 --radius: 8px; --transition: 180ms cubic-bezier(.4,0,.2,1);
64 --safe-top: env(safe-area-inset-top, 0); --safe-bot: env(safe-area-inset-bottom, 0);
65 /* iOS top inset: starts from env(), but a tiny boot script overrides it with a
66 real/measured value (env() resolves to 0 in some iOS standalone states). */
67 --ios-safe-top: env(safe-area-inset-top, 0px);
68 color-scheme: light dark;
69}
70
71/* Native controls (datum/tijd-picker, scrollbars) het SITE-thema laten volgen i.p.v.
72 de OS-voorkeur, en de datum/tijd-velden de site-accentkleur geven. Zo staat de
73 ingebouwde kalender-popup in dark + accent (de popup zelf is een browser-widget,
74 dus fonts/randen blijven van de browser). */
75[data-theme="dark"] { color-scheme: dark; }
76[data-theme="light"] { color-scheme: light; }
77input[type="date"], input[type="time"], input[type="datetime-local"] { accent-color: var(--accent, #6b8f71); }
78input[type="date"]::-webkit-calendar-picker-indicator,
79input[type="time"]::-webkit-calendar-picker-indicator,
80input[type="datetime-local"]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: .7; }
81input[type="date"]:hover::-webkit-calendar-picker-indicator,
82input[type="time"]:hover::-webkit-calendar-picker-indicator,
83input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator { opacity: 1; }
84
85/* ============================================================
86 PALETTES — elk palette definieert alleen bg/tekst/rand shades.
87 --accent wordt LOS ingesteld via de accent-kleur config (inline in template).
88 Palette-selector: <html data-palette="forest"> en optioneel data-theme="dark"|"light".
89 Als geen data-palette = Sage default.
90 ============================================================ */
91
92/* ── SAGE (default) ── warme crème ── */
93:root,
94[data-palette="sage"] {
95 --paper: #faf8f3; --paper-2: #f2ede0;
96 --ink: #1a1a1a; --ink-soft: #3d3833; --ink-muted: #6b6560; --ink-faint: #a8a29e;
97 --rule: #e8e2d5; --rule-2: #d4ccb8;
98}
99@media (prefers-color-scheme: dark) {
100 :root:not([data-theme="light"]):not([data-palette]),
101 [data-palette="sage"]:not([data-theme="light"]) {
102 --paper: #1c1a17; --paper-2: #252220;
103 --ink: #f4ede0; --ink-soft: #d4ccb8; --ink-muted: #a8a29e; --ink-faint: #6b6560;
104 --rule: #3d3833; --rule-2: #4d4740;
105 }
106}
107[data-theme="dark"]:not([data-palette]),
108[data-theme="dark"][data-palette="sage"] {
109 --paper: #1c1a17; --paper-2: #252220;
110 --ink: #f4ede0; --ink-soft: #d4ccb8; --ink-muted: #a8a29e; --ink-faint: #6b6560;
111 --rule: #3d3833; --rule-2: #4d4740;
112}
113
114/* ── KLONKT ── merk-standaard: clean wit → bijna-zwart (neutraal, gouden accent) ── */
115[data-palette="klonkt"] {
116 --paper: #ffffff; --paper-2: #f4f4f5;
117 --ink: #09090b; --ink-soft: #27272a; --ink-muted: #52525b; --ink-faint: #a1a1aa;
118 --rule: #e4e4e7; --rule-2: #d4d4d8;
119}
120@media (prefers-color-scheme: dark) {
121 [data-palette="klonkt"]:not([data-theme="light"]) {
122 --paper: #0a0a0a; --paper-2: #18181b;
123 --ink: #fafafa; --ink-soft: #d4d4d8; --ink-muted: #a1a1aa; --ink-faint: #71717a;
124 --rule: #27272a; --rule-2: #3f3f46;
125 }
126}
127[data-theme="dark"][data-palette="klonkt"] {
128 --paper: #0a0a0a; --paper-2: #18181b;
129 --ink: #fafafa; --ink-soft: #d4d4d8; --ink-muted: #a1a1aa; --ink-faint: #71717a;
130 --rule: #27272a; --rule-2: #3f3f46;
131}
132
133/* ── PAPER ── minimalistisch wit → zwart ── */
134[data-palette="paper"] {
135 --paper: #ffffff; --paper-2: #f4f4f5;
136 --ink: #09090b; --ink-soft: #27272a; --ink-muted: #52525b; --ink-faint: #a1a1aa;
137 --rule: #e4e4e7; --rule-2: #d4d4d8;
138}
139@media (prefers-color-scheme: dark) {
140 [data-palette="paper"]:not([data-theme="light"]) {
141 --paper: #0a0a0a; --paper-2: #18181b;
142 --ink: #fafafa; --ink-soft: #d4d4d8; --ink-muted: #a1a1aa; --ink-faint: #71717a;
143 --rule: #27272a; --rule-2: #3f3f46;
144 }
145}
146[data-theme="dark"][data-palette="paper"] {
147 --paper: #0a0a0a; --paper-2: #18181b;
148 --ink: #fafafa; --ink-soft: #d4d4d8; --ink-muted: #a1a1aa; --ink-faint: #71717a;
149 --rule: #27272a; --rule-2: #3f3f46;
150}
151
152
153/* ── FOREST ── olijfgroen → donker bos ── */
154[data-palette="forest"] {
155 --paper: #f2f6ed; --paper-2: #e1ead6;
156 --ink: #1a2e15; --ink-soft: #2d4a26; --ink-muted: #5a6f52; --ink-faint: #8aa080;
157 --rule: #ccddbd; --rule-2: #adc396;
158}
159@media (prefers-color-scheme: dark) {
160 [data-palette="forest"]:not([data-theme="light"]) {
161 --paper: #0d1f12; --paper-2: #1a331e;
162 --ink: #dcf2d0; --ink-soft: #b8d8a8; --ink-muted: #8aad7c; --ink-faint: #5a7a50;
163 --rule: #2d4a30; --rule-2: #3d5e42;
164 }
165}
166[data-theme="dark"][data-palette="forest"] {
167 --paper: #0d1f12; --paper-2: #1a331e;
168 --ink: #dcf2d0; --ink-soft: #b8d8a8; --ink-muted: #8aad7c; --ink-faint: #5a7a50;
169 --rule: #2d4a30; --rule-2: #3d5e42;
170}
171
172/* ── STONE ── beige bruin → koffie ── */
173[data-palette="stone"] {
174 --paper: #f5f0e8; --paper-2: #e7ddce;
175 --ink: #2b2218; --ink-soft: #4a3a2a; --ink-muted: #78614a; --ink-faint: #a8927b;
176 --rule: #d6c6ac; --rule-2: #bda98a;
177}
178@media (prefers-color-scheme: dark) {
179 [data-palette="stone"]:not([data-theme="light"]) {
180 --paper: #1a130b; --paper-2: #2d2416;
181 --ink: #f5e9d5; --ink-soft: #d4c0a3; --ink-muted: #a8927b; --ink-faint: #786452;
182 --rule: #3d2f1e; --rule-2: #534029;
183 }
184}
185[data-theme="dark"][data-palette="stone"] {
186 --paper: #1a130b; --paper-2: #2d2416;
187 --ink: #f5e9d5; --ink-soft: #d4c0a3; --ink-muted: #a8927b; --ink-faint: #786452;
188 --rule: #3d2f1e; --rule-2: #534029;
189}
190
191/* ── MIDNIGHT ── lavendel → donker paars ── */
192[data-palette="midnight"] {
193 --paper: #f3f1f8; --paper-2: #e3ddf0;
194 --ink: #1e1a2e; --ink-soft: #332c4d; --ink-muted: #5e5478; --ink-faint: #9288a8;
195 --rule: #d4cae3; --rule-2: #b8a9cc;
196}
197@media (prefers-color-scheme: dark) {
198 [data-palette="midnight"]:not([data-theme="light"]) {
199 --paper: #0f0a1f; --paper-2: #1c1432;
200 --ink: #e9def7; --ink-soft: #c4b5d9; --ink-muted: #9d88b8; --ink-faint: #6b5a85;
201 --rule: #2d1f4a; --rule-2: #3d2b5e;
202 }
203}
204[data-theme="dark"][data-palette="midnight"] {
205 --paper: #0f0a1f; --paper-2: #1c1432;
206 --ink: #e9def7; --ink-soft: #c4b5d9; --ink-muted: #9d88b8; --ink-faint: #6b5a85;
207 --rule: #2d1f4a; --rule-2: #3d2b5e;
208}
209
210/* ── SUNSET ── roze crème → diep paars-roze ── */
211[data-palette="sunset"] {
212 --paper: #fdf4f3; --paper-2: #f7e1dc;
213 --ink: #2e1618; --ink-soft: #4d282b; --ink-muted: #7a4a4e; --ink-faint: #b08589;
214 --rule: #ebcac3; --rule-2: #d9a8a0;
215}
216@media (prefers-color-scheme: dark) {
217 [data-palette="sunset"]:not([data-theme="light"]) {
218 --paper: #1f0a14; --paper-2: #321525;
219 --ink: #fce7f3; --ink-soft: #f0c5d3; --ink-muted: #c896a8; --ink-faint: #8a6878;
220 --rule: #4a1f35; --rule-2: #5e2d43;
221 }
222}
223[data-theme="dark"][data-palette="sunset"] {
224 --paper: #1f0a14; --paper-2: #321525;
225 --ink: #fce7f3; --ink-soft: #f0c5d3; --ink-muted: #c896a8; --ink-faint: #8a6878;
226 --rule: #4a1f35; --rule-2: #5e2d43;
227}
228
229/* ── SAND ── warm papier (subtiel, niet fel geel) → warm donker ── (key blijft 'cream') */
230[data-palette="cream"] {
231 --paper: #f7f3ec; --paper-2: #ece5d8;
232 --ink: #232019; --ink-soft: #43392c; --ink-muted: #6f6149; --ink-faint: #a3957c;
233 --rule: #ddd3c0; --rule-2: #c9bca3;
234}
235@media (prefers-color-scheme: dark) {
236 [data-palette="cream"]:not([data-theme="light"]) {
237 --paper: #14120d; --paper-2: #221e15;
238 --ink: #efe9dd; --ink-soft: #d0c6b2; --ink-muted: #a3957c; --ink-faint: #6f6149;
239 --rule: #322c20; --rule-2: #463d2c;
240 }
241}
242[data-theme="dark"][data-palette="cream"] {
243 --paper: #14120d; --paper-2: #221e15;
244 --ink: #efe9dd; --ink-soft: #d0c6b2; --ink-muted: #a3957c; --ink-faint: #6f6149;
245 --rule: #322c20; --rule-2: #463d2c;
246}
247
248/* ── OCEAN ── helder blauw → diep oceaanblauw ── */
249[data-palette="ocean"] {
250 --paper: #eef4fb; --paper-2: #d8e6f7;
251 --ink: #0f2942; --ink-soft: #1d4368; --ink-muted: #4a6e90; --ink-faint: #87a3c0;
252 --rule: #c2d8ee; --rule-2: #a3c2e0;
253}
254@media (prefers-color-scheme: dark) {
255 [data-palette="ocean"]:not([data-theme="light"]) {
256 --paper: #081726; --paper-2: #102a42;
257 --ink: #d6e8fb; --ink-soft: #aecbe8; --ink-muted: #7e9fc0; --ink-faint: #547390;
258 --rule: #1d3a56; --rule-2: #2a4d6e;
259 }
260}
261[data-theme="dark"][data-palette="ocean"] {
262 --paper: #081726; --paper-2: #102a42;
263 --ink: #d6e8fb; --ink-soft: #aecbe8; --ink-muted: #7e9fc0; --ink-faint: #547390;
264 --rule: #1d3a56; --rule-2: #2a4d6e;
265}
266
267/* ── TEAL ── mint-turquoise → diep teal ── */
268[data-palette="teal"] {
269 --paper: #ecf7f5; --paper-2: #cfe9e4;
270 --ink: #0c2e2a; --ink-soft: #194a44; --ink-muted: #467168; --ink-faint: #84aaa2;
271 --rule: #bce0d9; --rule-2: #9bcbc1;
272}
273@media (prefers-color-scheme: dark) {
274 [data-palette="teal"]:not([data-theme="light"]) {
275 --paper: #06201d; --paper-2: #0e332e;
276 --ink: #d4f2ec; --ink-soft: #aad9d0; --ink-muted: #7aaaa0; --ink-faint: #517a72;
277 --rule: #1a4a42; --rule-2: #275e54;
278 }
279}
280[data-theme="dark"][data-palette="teal"] {
281 --paper: #06201d; --paper-2: #0e332e;
282 --ink: #d4f2ec; --ink-soft: #aad9d0; --ink-muted: #7aaaa0; --ink-faint: #517a72;
283 --rule: #1a4a42; --rule-2: #275e54;
284}
285
286/* ── CANDY ── zacht roze-rood → diep kersenrood ── */
287[data-palette="candy"] {
288 --paper: #fdf1f3; --paper-2: #f8d8de;
289 --ink: #3a1018; --ink-soft: #5e1f2a; --ink-muted: #8e4450; --ink-faint: #c2868f;
290 --rule: #f0c5cd; --rule-2: #e3a0ab;
291}
292@media (prefers-color-scheme: dark) {
293 [data-palette="candy"]:not([data-theme="light"]) {
294 --paper: #220810; --paper-2: #3a121d;
295 --ink: #fde0e6; --ink-soft: #f5b8c4; --ink-muted: #cd8b98; --ink-faint: #8e5f6a;
296 --rule: #4d1a28; --rule-2: #632536;
297 }
298}
299[data-theme="dark"][data-palette="candy"] {
300 --paper: #220810; --paper-2: #3a121d;
301 --ink: #fde0e6; --ink-soft: #f5b8c4; --ink-muted: #cd8b98; --ink-faint: #8e5f6a;
302 --rule: #4d1a28; --rule-2: #632536;
303}
304
305/* ── AMBER ── warm honing → diep amber ── */
306[data-palette="amber"] {
307 --paper: #fdf6e9; --paper-2: #f7e6c2;
308 --ink: #3a2a0c; --ink-soft: #5e451a; --ink-muted: #8e7340; --ink-faint: #c2a877;
309 --rule: #f0dca8; --rule-2: #e3c581;
310}
311@media (prefers-color-scheme: dark) {
312 [data-palette="amber"]:not([data-theme="light"]) {
313 --paper: #221a08; --paper-2: #3a2c12;
314 --ink: #fdeecb; --ink-soft: #f0d49a; --ink-muted: #c2a877; --ink-faint: #8e7340;
315 --rule: #4d3a16; --rule-2: #634d20;
316 }
317}
318[data-theme="dark"][data-palette="amber"] {
319 --paper: #221a08; --paper-2: #3a2c12;
320 --ink: #fdeecb; --ink-soft: #f0d49a; --ink-muted: #c2a877; --ink-faint: #8e7340;
321 --rule: #4d3a16; --rule-2: #634d20;
322}
323
324/* ── ROSE ── zacht roze → wijnrood ── */
325[data-palette="rose"] {
326 --paper: #fdf2f4; --paper-2: #f8dde3;
327 --ink: #2e1419; --ink-soft: #4d242c; --ink-muted: #7a4651; --ink-faint: #b3838d;
328 --rule: #f0c9d1; --rule-2: #e0a3af;
329}
330@media (prefers-color-scheme: dark) {
331 [data-palette="rose"]:not([data-theme="light"]) {
332 --paper: #1f0a0f; --paper-2: #33141c;
333 --ink: #fce4ea; --ink-soft: #f0bcc8; --ink-muted: #c98f9d; --ink-faint: #8a6470;
334 --rule: #4a1f2c; --rule-2: #5e2d3a;
335 }
336}
337[data-theme="dark"][data-palette="rose"] {
338 --paper: #1f0a0f; --paper-2: #33141c;
339 --ink: #fce4ea; --ink-soft: #f0bcc8; --ink-muted: #c98f9d; --ink-faint: #8a6470;
340 --rule: #4a1f2c; --rule-2: #5e2d3a;
341}
342
343
344/* ── TERRACOTTA ── warme klei → diep brick ── (key blijft 'mint' voor DB-compat) */
345[data-palette="mint"] {
346 --paper: #faf2ee; --paper-2: #f2ddd0;
347 --ink: #2e1a12; --ink-soft: #4a2c1e; --ink-muted: #7a5544; --ink-faint: #b3917e;
348 --rule: #eccdbb; --rule-2: #ddb49d;
349}
350@media (prefers-color-scheme: dark) {
351 [data-palette="mint"]:not([data-theme="light"]) {
352 --paper: #1f120c; --paper-2: #2e1c13;
353 --ink: #f7e6da; --ink-soft: #e0c3b0; --ink-muted: #b3917c; --ink-faint: #7a5544;
354 --rule: #4a2c1e; --rule-2: #5e3a28;
355 }
356}
357[data-theme="dark"][data-palette="mint"] {
358 --paper: #1f120c; --paper-2: #2e1c13;
359 --ink: #f7e6da; --ink-soft: #e0c3b0; --ink-muted: #b3917c; --ink-faint: #7a5544;
360 --rule: #4a2c1e; --rule-2: #5e3a28;
361}
362
363/* ── LILAC ── zacht lila → donker violet ── */
364[data-palette="lilac"] {
365 --paper: #faf4fb; --paper-2: #f0e0f3;
366 --ink: #2a1830; --ink-soft: #46294f; --ink-muted: #7a5685; --ink-faint: #b393bd;
367 --rule: #e6cdec; --rule-2: #d4abdd;
368}
369@media (prefers-color-scheme: dark) {
370 [data-palette="lilac"]:not([data-theme="light"]) {
371 --paper: #170a1c; --paper-2: #281433;
372 --ink: #f3e2f7; --ink-soft: #dabce4; --ink-muted: #b088c0; --ink-faint: #7a5a88;
373 --rule: #3d1f4a; --rule-2: #4f2b5e;
374 }
375}
376[data-theme="dark"][data-palette="lilac"] {
377 --paper: #170a1c; --paper-2: #281433;
378 --ink: #f3e2f7; --ink-soft: #dabce4; --ink-muted: #b088c0; --ink-faint: #7a5a88;
379 --rule: #3d1f4a; --rule-2: #4f2b5e;
380}
381
382/* Accent-tint wordt berekend uit --accent, zodat hij meegaat bij elke accent-keuze.
383 Wordt in template inline gezet; hier alleen een fallback. */
384:root { --accent: #c2410c; --accent-soft: #ea580c; --accent-tint: #fef2e8; }
385
386* { box-sizing: border-box; }
387html {
388 -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent;
389 overscroll-behavior-y: none;
390 /* Horizontaal clippen op ROOT-niveau: dit propageert naar de viewport (geen
391 horizontale scroll) ZONDER position:fixed te breken — html is sowieso de
392 document-scroller. De body mag GEEN overflow-x krijgen, want dan zou die een
393 tweede scroll-container worden en zou de fixed bottom-tab meeschuiven. */
394 overflow-x: hidden;
395}
396body {
397 margin: 0;
398}
399
400/* ── Thema-scrollbar: slank, afgerond, subtiel — vervangt de standaard chunky
401 browser-scrollbar (met pijltjes) die niet bij het donkere thema past.
402 Werkt op de pagina én op interne scrollers (queue, chat-thread, dropdowns). ── */
403* {
404 scrollbar-width: thin;
405 scrollbar-color: color-mix(in srgb, var(--ink) 28%, transparent) transparent;
406}
407::-webkit-scrollbar { width: 10px; height: 10px; }
408::-webkit-scrollbar-track { background: transparent; }
409::-webkit-scrollbar-thumb {
410 background-color: color-mix(in srgb, var(--ink) 24%, transparent);
411 border-radius: 999px;
412 border: 2px solid transparent; /* transparante rand → optisch slanker (≈6px) */
413 background-clip: content-box;
414}
415::-webkit-scrollbar-thumb:hover {
416 background-color: color-mix(in srgb, var(--accent) 60%, var(--ink));
417}
418::-webkit-scrollbar-corner { background: transparent; }
419
420/* Login/auth = focus-scherm. Bij htmx-navigatie naar login blijft de bottom-tab
421 uit de vorige pagina in de DOM staan → hier verbergen zodat het login-scherm
422 net zo "kaal" is als bij een full-load (waar de tab niet eens gerenderd wordt). */
423body.on-auth .bottom-tab { display: none; }
424body:not(.admin) {
425 min-height: 100dvh;
426 background: var(--paper); color: var(--ink);
427 font-family: var(--font-body); font-size: 1.0625rem; line-height: 1.65;
428 font-feature-settings: "liga" 1, "kern" 1, "onum" 1;
429 -webkit-font-smoothing: antialiased;
430 /* v9.4 — Sticky footer: body als flex-kolom, main groeit, footer onderaan */
431 display: flex;
432 flex-direction: column;
433}
434body:not(.admin) #pcms-main { flex: 1 0 auto; }
435body:not(.admin) .site-footer { flex-shrink: 0; }
436body:not(.admin)::before {
437 content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
438 /* Per-palette achtergrond-gradient: opgebouwd uit de palette's EIGEN --paper/--paper-2
439 (diagonale verloop) + een zachte accent-glow erbovenop. Werkt automatisch voor elk
440 palet, light én dark — geen per-palette regels nodig. */
441 background: radial-gradient(ellipse at top, color-mix(in srgb, var(--accent) 6%, transparent), transparent 60%),
442 radial-gradient(ellipse at bottom right, color-mix(in srgb, var(--accent) 7%, transparent), transparent 55%),
443 linear-gradient(160deg, var(--paper) 0%, var(--paper-2) 100%);
444}
445/* Klonkt-palet gebruikt nu (net als de andere paletten) de generieke accent-glow
446 hierboven → de achtergrond-gradient volgt de gekozen accentkleur. */
447::selection { background: var(--accent-tint); color: var(--accent); }
448
449h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 450; line-height: 1.15; letter-spacing: -0.015em; margin: 0; text-wrap: balance; font-variation-settings: "opsz" 144, "SOFT" 50; }
450h1 { font-size: clamp(2rem, 4vw + 1rem, 3.5rem); letter-spacing: -0.022em; }
451h2 { font-size: clamp(1.5rem, 2vw + 1rem, 2.25rem); margin: 1.5rem 0 .4rem; }
452h3 { font-size: 1.375rem; margin: 1.25rem 0 .3rem; }
453p { margin: 0 0 .85em; text-wrap: pretty; hyphens: auto; }
454a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--rule-2); text-underline-offset: 3px; transition: color var(--transition), text-decoration-color var(--transition); }
455a:hover { color: var(--accent); text-decoration-color: var(--accent); }
456/* Knop-ankers houden hun eigen tekstkleur bij hover. Zonder dit overschrijft de
457 globale a:hover{color:accent} de knop-tekst → die wordt dezelfde kleur als de
458 accent-achtergrond en valt weg (vooral op sites met een felle accent). */
459a.btn:hover, a.epk-btn:hover { color: var(--ink); }
460a.btn-primary:hover, a.btn-danger:hover, a.btn-success:hover, a.button:hover,
461a.epk-btn-primary:hover, a.dls-btn:hover, a.sh-tix:hover, a.dl-go:hover { color: #fff; text-decoration-color: currentColor; }
462a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; text-decoration: none; }
463blockquote { margin: 2em 0; padding: .25em 0 .25em 1.25em; border-left: 2px solid var(--accent); font-family: var(--font-display); font-style: italic; font-size: 1.15em; color: var(--ink-soft); }
464code { font-family: var(--font-mono); font-size: .9em; padding: .15em .4em; background: var(--paper-2); border: 1px solid var(--rule); border-radius: 4px; }
465pre { font-family: var(--font-mono); font-size: .85rem; padding: 1.25em 1.5em; background: var(--paper-2); border: 1px solid var(--rule); border-radius: var(--radius); overflow-x: auto; line-height: 1.5; }
466pre code { padding: 0; background: none; border: none; }
467hr { border: 0; border-top: 1px solid var(--rule); margin: 3em auto; max-width: 4rem; }
468
469/* Container — schaalt mee met schermgrootte.
470 42rem default (optimale leesbreedte voor tekst),
471 breder op HD/2.5K/4K waar je meer ademruimte hebt.
472 Grid-view heeft z'n eigen bredere variant (zie .feed-grid). */
473/* Container max-width schaalt per schermformaat.
474 42rem is optimale leesbreedte voor tekst. Op grotere schermen
475 ademruimte geven zonder uitwaaieren. Grid apart geregeld. */
476.container { max-width: 42rem; margin-inline: auto; padding-inline: clamp(1.25rem, 4vw, 2rem); }
477
478/* Post-/leesbreedte. Globaal + hogere specificity (.container.post-page) zodat 'ie
479 de responsive .container-breakpoints (56/72rem) overal overrult — posts én de
480 downloads-pagina krijgen zo exact dezelfde 720px-breedte. */
481.container.post-page { max-width: 720px; margin: 0.5rem auto 2rem; padding: 0 1rem; }
482
483/* Laptop / Full HD — 1440px viewport of groter */
484@media (min-width: 1440px) {
485 .container { max-width: 56rem; }
486}
487/* Desktop / QHD 2.5K — 1920px viewport of groter */
488@media (min-width: 1920px) {
489 .container { max-width: 72rem; }
490}
491/* 4K UHD — 2560px viewport of groter */
492@media (min-width: 2560px) {
493 .container { max-width: 88rem; }
494}
495
496/* Grid-view tiles: Instagram-feel. Max-width schaalt met gekozen kolommen zodat
497 tegels niet te groot of te klein worden. */
498@media (min-width: 1200px) {
499 body[data-grid-cols="4"] .feed-grid.container { max-width: 80rem; }
500 body[data-grid-cols="3"] .feed-grid.container { max-width: 64rem; }
501 body[data-grid-cols="2"] .feed-grid.container { max-width: 48rem; }
502}
503@media (min-width: 1920px) {
504 body[data-grid-cols="4"] .feed-grid.container { max-width: 96rem; }
505}
506
507.icon { width: 1.125em; height: 1.125em; flex-shrink: 0; vertical-align: -0.15em; stroke: currentColor; fill: none; display: inline-block; }
508
509/* Masthead */
510.masthead {
511 border-bottom: 1px solid var(--rule);
512 padding: calc(1rem + var(--ios-safe-top, 0px)) 0 1rem;
513 /* GEEN backdrop-filter hier: een voorouder met backdrop-filter blokkeert de
514 frosted blur van het user-menu-dropdown eronder. Masthead is toch bijna
515 dekkend, dus solide bg i.p.v. blur. */
516 background: color-mix(in srgb, var(--paper) 94%, transparent);
517 position: sticky; top: 0; z-index: 20;
518}
519.masthead-inner { display: flex; align-items: center; justify-content: flex-end; gap: 1.5rem; }
520.masthead-brand { min-width: 0; flex: 1 1 auto; overflow: hidden; }
521.site-title { font-family: var(--font-display); font-size: 1.5rem; font-weight: 500; font-variation-settings: "opsz" 72, "SOFT" 100; letter-spacing: -0.015em; text-decoration: none; color: var(--ink); line-height: 1; display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
522.site-title:hover { color: var(--accent); }
523/* v9.0 — nav-home icon (replaces site-title text in nav) */
524.nav-home {
525 display: inline-flex; align-items: center; justify-content: center;
526 width: 2.25rem; height: 2.25rem;
527 color: var(--ink-soft); text-decoration: none;
528 border-radius: 6px; border: 1px solid transparent;
529 transition: all var(--transition);
530}
531.nav-home:hover { color: var(--ink); background: var(--paper-2); border-color: var(--rule); }
532.nav-home .icon { width: 1.15rem; height: 1.15rem; }
533.top-nav { display: flex; align-items: center; gap: .25rem; flex-shrink: 0; }
534.nav-link, .nav-btn {
535 font-family: var(--font-ui); font-size: .875rem; font-weight: 500;
536 color: var(--ink-soft); text-decoration: none;
537 padding: .5rem .85rem; border-radius: 6px;
538 background: transparent; border: 1px solid transparent;
539 cursor: pointer;
540 display: inline-flex; align-items: center; gap: .4rem;
541 min-height: 2.25rem;
542 transition: all var(--transition);
543}
544.nav-link:hover, .nav-btn:hover { color: var(--ink); background: var(--paper-2); border-color: var(--rule); }
545.nav-link-muted { color: var(--ink-muted); }
546.nav-label { display: none; }
547@media (min-width: 560px) { .nav-label { display: inline; } }
548
549/* Article */
550main { padding-top: 2rem; }
551.page { padding-block: 2rem 3rem; }
552page-container { display: block; font-size: 1.125rem; line-height: 1.75; }
553page-container h1 { font-size: clamp(2rem, 5vw + 1rem, 3.75rem); margin-bottom: 1rem; letter-spacing: -0.025em; }
554page-container img, page-container iframe, page-container video { max-width: 100%; height: auto; display: block; margin: 2rem auto; border-radius: var(--radius); }
555page-container audio { width: 100%; margin: 1.5rem 0; }
556page-container figure { margin: 2rem 0; }
557page-container figcaption { font-family: var(--font-ui); font-size: .85rem; color: var(--ink-muted); text-align: center; margin-top: .5rem; }
558page-container[contenteditable="true"] { outline: 2px dashed var(--accent); outline-offset: .5rem; border-radius: var(--radius); }
559
560.empty { text-align: center; padding: 4rem 1rem; }
561/* Moved account (FEP-7628 slice 3): the signpost above the feed. Loud on
562 purpose — a visitor must not read a stale timeline thinking it is current. */
563.moved-banner {
564 text-align: center;
565 margin: 1.5rem 0 2rem;
566 padding: 1.75rem 1.25rem;
567 border: 2px solid var(--accent, #e8b04b);
568 border-radius: var(--radius, 10px);
569 background: color-mix(in srgb, var(--accent, #e8b04b) 10%, var(--paper-2, var(--paper)));
570}
571.moved-banner-lead { margin: 0 0 .5rem; font-size: 1rem; opacity: .85; }
572.moved-banner-link {
573 display: inline-block;
574 font-family: var(--font-display);
575 font-size: clamp(1.5rem, 5vw, 2.4rem);
576 font-weight: 700;
577 line-height: 1.15;
578 overflow-wrap: anywhere;
579}
580.moved-banner-hint { margin: .75rem 0 0; font-size: .85rem; color: var(--ink-soft); }
581.empty h1 { font-size: 2rem; }
582.empty p { color: var(--ink-muted); }
583
584/* Embeds */
585.pcms-embed, .folio-embed { margin: 2rem 0; }
586.pcms-embed iframe, .pcms-embed video, .pcms-embed audio,
587.folio-embed iframe, .folio-embed video, .folio-embed audio { width: 100%; display: block; border: 0; border-radius: var(--radius); }
588
589/* Article footer */
590.article-footer { display: flex; justify-content: center; padding-top: 2rem; margin-top: 2rem; border-top: 1px solid var(--rule); }
591
592/* Buttons */
593.button {
594 font-family: var(--font-ui); font-size: .875rem; font-weight: 500;
595 padding: .6rem 1.1rem; min-height: 2.5rem;
596 display: inline-flex; align-items: center; gap: .5rem;
597 background: var(--ink); color: var(--paper);
598 border: 1px solid var(--ink);
599 border-radius: 6px;
600 text-decoration: none; cursor: pointer;
601 transition: all var(--transition);
602}
603.button:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
604.button-ghost { background: transparent; color: var(--ink); border-color: var(--rule-2); }
605.button-ghost:hover { background: var(--paper-2); border-color: var(--accent); color: var(--accent); }
606
607/* Pagination */
608.pagination {
609 display: grid;
610 grid-template-columns: 1fr 1fr;
611 gap: 1rem;
612 padding-block: 2rem 4rem;
613 margin-top: 2rem;
614 border-top: 1px solid var(--rule);
615}
616a.pagination-item {
617 display: flex; align-items: center; gap: 1rem; padding: 1rem 1.25rem;
618 border: 2px solid var(--rule-2, var(--rule));
619 border-radius: var(--radius);
620 text-decoration: none; transition: all .15s ease; font-size: .9rem;
621 background: var(--paper-2);
622 min-height: 5rem;
623 min-width: 0;
624 overflow: hidden;
625 cursor: pointer;
626 box-shadow: 0 1px 0 rgba(0,0,0,.02);
627 -webkit-tap-highlight-color: color-mix(in srgb, var(--accent) 30%, transparent);
628 position: relative;
629}
630.pagination-item:not(a) {
631 display: flex; align-items: center; gap: 1rem; padding: 1rem 1.25rem;
632 border: 1px dashed var(--rule); border-radius: var(--radius);
633 font-size: .9rem; background: transparent; min-height: 5rem;
634 min-width: 0; overflow: hidden;
635}
636.pagination-next { flex-direction: row-reverse; text-align: right; }
637a.pagination-item:hover {
638 border-color: var(--accent);
639 background: color-mix(in srgb, var(--accent) 5%, var(--paper-2));
640 transform: translateY(-2px);
641 box-shadow: 0 4px 12px rgba(0,0,0,.08);
642}
643a.pagination-item:active {
644 transform: translateY(0);
645 transition-duration: .05s;
646}
647.pagination-disabled { opacity: .5; cursor: default; font-style: italic; }
648.pagination-body { display: flex; flex-direction: column; gap: .15rem; min-width: 0; flex: 1; }
649.pagination-label {
650 display: block; font-family: var(--font-ui); font-size: .7rem; font-weight: 700;
651 letter-spacing: .08em; text-transform: uppercase; color: var(--accent);
652 margin-bottom: .15rem;
653}
654.pagination-slug {
655 display: block; font-size: .72rem; color: var(--ink-muted);
656 opacity: .75; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
657 font-style: italic;
658}
659.pagination-title {
660 display: block; font-family: var(--font-display); font-weight: 600; color: var(--ink);
661 font-variation-settings: "opsz" 72; font-style: normal;
662 line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
663 font-size: 1.05rem;
664 text-decoration: underline;
665 text-decoration-color: var(--rule-2, var(--rule));
666 text-decoration-thickness: 1px;
667 text-underline-offset: 3px;
668 transition: text-decoration-color .15s;
669}
670a.pagination-item:hover .pagination-title {
671 text-decoration-color: var(--accent);
672}
673.pagination .icon {
674 width: 1.75em; height: 1.75em; flex-shrink: 0;
675 color: var(--accent);
676 transition: transform .15s;
677}
678a.pagination-prev:hover .icon { transform: translateX(-4px); }
679a.pagination-next:hover .icon { transform: translateX(4px); }
680
681/* Pinned-targets → accent-tint en dikkere rand voor duidelijkheid */
682.pagination-item.is-pinned {
683 background: color-mix(in srgb, var(--accent) 8%, var(--paper-2));
684 border-color: color-mix(in srgb, var(--accent) 45%, var(--rule));
685}
686a.pagination-item.is-pinned:hover {
687 background: color-mix(in srgb, var(--accent) 15%, var(--paper-2));
688 border-color: var(--accent);
689}
690
691@media (max-width: 800px) { .pagination { grid-template-columns: 1fr; } }
692
693/* Footer */
694.site-footer { padding: 2rem 0 calc(2rem + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--rule); margin-top: 4rem; font-family: var(--font-ui); font-size: .85rem; color: var(--ink-muted); }
695.site-footer-inner { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 1rem; align-items: center; }
696.site-footer a { color: var(--ink-muted); text-decoration-color: var(--rule); }
697.site-footer a:hover { color: var(--accent); }
698.site-footer-links { display: flex; gap: 1rem; }
699.sep { color: var(--ink-faint); margin: 0 .5rem; }
700.footer-tagline { font-style: italic; opacity: .8; }
701
702@media print {
703 .masthead, .pagination, .site-footer, .article-footer, .top-nav { display: none; }
704 body { background: #fff; color: #000; }
705}
706@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation: none !important; } }
707
708/* ============================================================
709 V7 ADDITIONS — post metadata UI + audio player + post-images
710 ============================================================ */
711
712/* Post header */
713.post-header { margin: 0 0 2rem; }
714.post-cover {
715 margin: 0 0 1.5rem;
716 border-radius: 8px;
717 overflow: hidden;
718 background: color-mix(in srgb, var(--fg) 4%, transparent);
719}
720.post-cover img {
721 display: block;
722 width: 100%;
723 height: auto; /* volledige (niet-bijgesneden) hoogte */
724 /* geen max-height/object-fit: cover meer → de hele afbeelding toont,
725 volle containerbreedte, zijkanten gerespecteerd. */
726}
727.post-title { font-size: clamp(1.6rem, 4vw, 2.6rem); line-height: 1.15; margin: 0 0 .5rem; letter-spacing: -.02em; }
728
729/* Pin banner — duidelijk zichtbaar dat een post gepind is */
730.post-pin-banner {
731 display: inline-flex;
732 align-items: center;
733 gap: .5rem;
734 background: color-mix(in srgb, var(--accent) 14%, transparent);
735 border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
736 color: var(--accent);
737 padding: .4rem .8rem;
738 border-radius: 999px;
739 font-size: .75rem;
740 font-weight: 600;
741 text-transform: uppercase;
742 letter-spacing: .08em;
743 margin: 0 0 .85rem;
744 line-height: 1;
745}
746.post-pin-banner-icon { font-size: 1rem; line-height: 1; }
747.post-pin-banner-sep { opacity: .5; }
748.post-pin-banner-pos { opacity: .85; }
749.post-date {
750 color: var(--fg-muted, #888);
751 font-size: .85rem;
752 letter-spacing: .05em;
753 text-transform: uppercase;
754 margin: 0 0 1.5rem;
755}
756
757/* Post-images in content (resize + align) */
758.post-image {
759 margin: 1.5rem 0;
760}
761.post-image img {
762 display: block;
763 height: auto;
764 border-radius: 6px;
765 max-width: 100%;
766}
767.post-image figcaption {
768 font-size: .85rem;
769 color: var(--fg-muted, #888);
770 margin-top: .5rem;
771 font-style: italic;
772 text-align: center;
773}
774.post-image--small img { max-width: 240px; }
775.post-image--medium img { max-width: 440px; }
776.post-image--large img { max-width: 720px; }
777.post-image--full img { width: 100%; max-width: 100%; }
778.post-image--left { text-align: left; }
779.post-image--left img { margin-left: 0; margin-right: auto; }
780.post-image--center { text-align: center; }
781.post-image--center img { margin-left: auto; margin-right: auto; }
782.post-image--right { text-align: right; }
783.post-image--right img { margin-left: auto; margin-right: 0; }
784
785/* Afbeeldingen in de post-tekst vullen ALTIJD de containerbreedte en houden hun
786 natuurlijke (niet-bijgesneden) hoogte — geen vaste hoogte / geen crop. */
787.post-content img {
788 display: block;
789 width: 100%;
790 max-width: 100%;
791 height: auto;
792 border-radius: 6px;
793 margin: 1.4em auto;
794}
795
796/* Video in de post-tekst (C2S-uploads uit Shaer): dezelfde maatvoering als
797 afbeeldingen, plus een plafond. Zonder deze regel rendert een <video> op
798 zijn natuurlijke maat en duwt een portret-video de hele kolom vol; met
799 object-fit blijft het beeld heel binnen het kader. Geldt ook voor de
800 Krant/Berichten (tl-content), waar dezelfde content langskomt. */
801.post-content video, .tl-content video {
802 display: block;
803 width: 100%;
804 max-width: 100%;
805 max-height: min(70vh, 540px);
806 height: auto;
807 object-fit: contain;
808 background: #000;
809 border-radius: 6px;
810 margin: 1.4em auto;
811}
812.post-content audio, .tl-content audio { width: 100%; display: block; margin: 1em auto; }
813
814/* Mini-player + bottom-tab clearance: applied to .pcms-main so the footer
815 is NOT pushed below the viewport bottom. The bars are position:fixed so
816 they overlap whatever they sit on top of; the padding ensures the last
817 content row isn't covered. Footer naturally follows main and now sits
818 exactly at viewport-bottom on short pages (sticky footer flex). */
819.pcms-main { padding-bottom: 5.5rem; }
820body.has-audio-player .pcms-main { padding-bottom: 5.5rem; }
821
822/* Mobiel toetsenbord open (body.kb-open, gezet via visualViewport in shell.ejs):
823 verberg de vaste onderbalken — anders zweven de bottom-tab + mini-speler boven
824 het toetsenbord of overlappen ze het invoerveld. Ze komen terug zodra het
825 toetsenbord sluit. De extra clearance onderaan is dan ook niet meer nodig. */
826body.kb-open .bottom-tab,
827body.kb-open .audio-player { display: none !important; }
828body.kb-open .pcms-main { padding-bottom: 1rem; }
829
830/* Mobiel & tablet (touch): scrollbalken verbergen — scrollen blijft werken, alleen
831 de balk-UI is weg (geen verwarrende/dubbele balken). */
832@media (pointer: coarse) {
833 * { scrollbar-width: none; -ms-overflow-style: none; }
834 *::-webkit-scrollbar { width: 0; height: 0; display: none; }
835}
836
837/* Afbeeldingen lastiger op te slaan (frictie, geen echte beveiliging): geen
838 sleep-naar-bureaublad, geen iOS long-press-bewaarmenu. Rechtsklik wordt in JS
839 geblokkeerd (zie shell.ejs). Covers/hero zijn al CSS-achtergronden = niet via
840 "afbeelding opslaan" te pakken. */
841img { -webkit-user-drag: none; -khtml-user-drag: none; -moz-user-drag: none; user-drag: none; -webkit-touch-callout: none; }
842
843/* ============================================================
844 AUDIO PLAYER v7.1 — SVG iconen, thema-aware, geen emoji
845 ============================================================ */
846.audio-player {
847 position: fixed;
848 left: 0; right: 0; bottom: 0;
849 background: color-mix(in srgb, var(--paper, #fff) 96%, var(--ink, #000));
850 border-top: 1px solid var(--rule, rgba(0,0,0,.1));
851 color: var(--ink, #222);
852 z-index: 1000;
853 backdrop-filter: blur(12px);
854 -webkit-backdrop-filter: blur(12px);
855 box-shadow: 0 -4px 20px rgba(0,0,0,.04);
856}
857[data-theme="dark"] .audio-player {
858 background: color-mix(in srgb, var(--paper, #1a1a1a) 92%, #fff);
859 box-shadow: 0 -4px 20px rgba(0,0,0,.3);
860}
861.audio-player-inner {
862 display: grid;
863 grid-template-columns: minmax(0, 1.6fr) auto minmax(180px, 2fr) auto;
864 gap: 1rem;
865 align-items: center;
866 padding: .65rem 1.25rem;
867 max-width: 1400px;
868 margin: 0 auto;
869}
870
871/* v9.0 — Clickable trigger dat cover + meta combineert zodat klikken erop sheet opent */
872.audio-player-expand-trigger {
873 display: flex;
874 align-items: center;
875 gap: .65rem;
876 min-width: 0;
877 background: none;
878 border: none;
879 padding: 0;
880 margin: 0;
881 cursor: pointer;
882 color: inherit;
883 text-align: left;
884 font: inherit;
885 border-radius: 6px;
886 transition: background .15s;
887}
888.audio-player-expand-trigger:hover {
889 background: color-mix(in srgb, var(--ink, #000) 6%, transparent);
890}
891
892/* Cover art */
893.audio-player-cover {
894 width: 48px; height: 48px;
895 border-radius: 4px;
896 background: linear-gradient(135deg,
897 var(--accent, #c2410c),
898 color-mix(in srgb, var(--accent, #c2410c) 55%, #000));
899 background-size: cover;
900 background-position: center;
901 flex-shrink: 0;
902 position: relative;
903}
904.audio-player-cover.has-image {
905 background-blend-mode: normal;
906}
907
908/* Meta — titel + artiest */
909.audio-player-meta {
910 min-width: 0;
911 display: flex;
912 flex-direction: column;
913 gap: 2px;
914}
915.audio-player-title-wrap {
916 overflow: hidden;
917 white-space: nowrap;
918 position: relative;
919}
920.audio-player-title {
921 display: inline-block;
922 font-family: var(--font-ui, inherit);
923 font-weight: 600;
924 font-size: .9rem;
925 line-height: 1.3;
926 letter-spacing: -.01em;
927 color: var(--ink, inherit);
928 white-space: nowrap;
929}
930.audio-player-title.is-overflowing {
931 animation: audio-title-marquee 6s ease-in-out infinite alternate;
932}
933@keyframes audio-title-marquee {
934 0%, 8% { transform: translateX(0); }
935 92%, 100% { transform: translateX(calc(-1 * var(--audio-shift, 0px))); }
936}
937.audio-player-artist {
938 font-family: var(--font-ui, inherit);
939 font-size: .74rem;
940 line-height: 1.3;
941 color: var(--ink-muted, rgba(0,0,0,.55));
942 white-space: nowrap;
943 overflow: hidden;
944 text-overflow: ellipsis;
945}
946
947/* Controls — prev / play / next */
948.audio-player-controls {
949 display: flex;
950 gap: .1rem;
951 align-items: center;
952}
953.audio-btn {
954 background: transparent;
955 border: none;
956 color: inherit;
957 cursor: pointer;
958 padding: .5rem;
959 border-radius: 50%;
960 transition: background .15s, color .15s, transform .08s;
961 display: inline-flex;
962 align-items: center;
963 justify-content: center;
964 position: relative;
965}
966.audio-btn svg {
967 width: 18px; height: 18px;
968 display: block;
969}
970.audio-btn:hover { background: color-mix(in srgb, var(--ink, #000) 8%, transparent); }
971.audio-btn:active { transform: scale(.94); }
972.audio-btn-play {
973 background: var(--accent, #c2410c);
974 color: #fff;
975 width: 38px; height: 38px;
976 padding: 0;
977}
978.audio-btn-play:hover {
979 background: color-mix(in srgb, var(--accent, #c2410c) 85%, #fff);
980}
981[data-theme="dark"] .audio-btn-play:hover {
982 background: color-mix(in srgb, var(--accent, #c2410c) 85%, #000);
983}
984.audio-btn-play svg { width: 16px; height: 16px; }
985.audio-btn-play .icon-pause { display: none; }
986.audio-player.is-playing .audio-btn-play .icon-play { display: none; }
987.audio-player.is-playing .audio-btn-play .icon-pause { display: block; }
988
989/* Progress bar */
990.audio-player-progress {
991 display: flex;
992 gap: .75rem;
993 align-items: center;
994 min-width: 0;
995}
996.audio-time {
997 font-size: .7rem;
998 color: var(--ink-muted, rgba(0,0,0,.55));
999 font-variant-numeric: tabular-nums;
1000 min-width: 2.7em;
1001 text-align: center;
1002}
1003.audio-seek {
1004 flex: 1;
1005 min-width: 0;
1006 cursor: pointer;
1007 padding: .5rem 0;
1008 position: relative;
1009}
1010.audio-seek-bar {
1011 height: 3px;
1012 background: color-mix(in srgb, var(--ink, #000) 12%, transparent);
1013 border-radius: 2px;
1014 overflow: hidden;
1015 transition: height .15s;
1016}
1017.audio-seek:hover .audio-seek-bar { height: 5px; }
1018.audio-seek-fill {
1019 height: 100%;
1020 background: var(--accent, #c2410c);
1021 width: 0%;
1022 transition: width .1s linear;
1023}
1024
1025/* Volume — popup on hover */
1026.audio-player-volume {
1027 position: relative;
1028 display: flex;
1029 align-items: center;
1030}
1031.audio-btn .icon-mute { display: none; }
1032.audio-player.is-muted .audio-btn .icon-vol { display: none; }
1033.audio-player.is-muted .audio-btn .icon-mute { display: block; }
1034.audio-volume-popup {
1035 position: absolute;
1036 bottom: calc(100% + 8px);
1037 left: 50%;
1038 transform: translateX(-50%) scale(.95);
1039 transform-origin: bottom center;
1040 background: var(--paper, #fff);
1041 border: 1px solid var(--rule, rgba(0,0,0,.1));
1042 border-radius: 8px;
1043 padding: .75rem .5rem;
1044 box-shadow: 0 4px 16px rgba(0,0,0,.15);
1045 opacity: 0;
1046 pointer-events: none;
1047 transition: opacity .15s, transform .15s, visibility .15s;
1048 height: 110px;
1049 visibility: hidden;
1050}
1051/* Invisible bridge tussen knop en popup zodat hover niet breekt */
1052.audio-volume-popup::after {
1053 content: '';
1054 position: absolute;
1055 bottom: -12px;
1056 left: -10px;
1057 right: -10px;
1058 height: 16px;
1059}
1060[data-theme="dark"] .audio-volume-popup {
1061 background: color-mix(in srgb, var(--paper, #111) 92%, #fff);
1062}
1063.audio-player-volume:hover .audio-volume-popup,
1064.audio-player-volume:focus-within .audio-volume-popup,
1065.audio-player-volume.is-open .audio-volume-popup {
1066 opacity: 1;
1067 visibility: visible;
1068 transform: translateX(-50%) scale(1);
1069 pointer-events: auto;
1070}
1071.audio-volume-popup input[type=range] {
1072 /* Standard vertical slider — replaces deprecated -webkit-appearance: slider-vertical. */
1073 writing-mode: vertical-lr;
1074 direction: rtl;
1075 width: 6px;
1076 height: 90px;
1077 accent-color: var(--accent, #c2410c);
1078 /* Grotere hit-area via pseudo-touch padding */
1079 padding: 0 12px;
1080 box-sizing: content-box;
1081 cursor: pointer;
1082}
1083
1084/* Mobile */
1085@media (max-width: 720px) {
1086 .audio-player-inner {
1087 /* v9.0 — 3 cols: expand-trigger (cover+meta) | controls | volume */
1088 grid-template-columns: minmax(0, 1fr) auto auto;
1089 gap: .5rem;
1090 padding: .5rem .8rem;
1091 }
1092 .audio-player-progress {
1093 display: none;
1094 }
1095 .audio-player-cover { width: 40px; height: 40px; }
1096 .audio-btn-play { width: 34px; height: 34px; }
1097 body.has-audio-player .pcms-main { padding-bottom: 4.2rem; }
1098 /* Verberg titel-artiest op bijzonder smal, verstop volume op mobile */
1099 .audio-player-volume { display: none; }
1100}
1101
1102/* Ultra-small schermen (iPhone 4 = 320px; iPhone SE 1st gen = 320px;
1103 iPhone mini ~360px). v9.3 — alles vanaf 320px moet werken; daaronder
1104 accepteren we wel/niet. */
1105@media (max-width: 380px) {
1106 .audio-player-inner {
1107 gap: .35rem;
1108 padding: .4rem .6rem;
1109 }
1110 .audio-player-expand-trigger {
1111 gap: .45rem;
1112 }
1113 .audio-player-cover { width: 36px; height: 36px; }
1114 .audio-player-title { font-size: .88rem; }
1115 .audio-player-artist { font-size: .72rem; }
1116 .audio-player-controls { gap: .15rem; }
1117 .audio-btn { width: 30px; height: 30px; }
1118 .audio-btn svg { width: 16px; height: 16px; }
1119 .audio-btn-play { width: 32px; height: 32px; }
1120 .audio-btn-play svg { width: 18px; height: 18px; }
1121
1122 /* v9.3 — Tracklist compact op smalle telefoons.
1123 Leader 28×28, kleinere gap, padding strakker. Tijd in monoscript blijft
1124 leesbaar; titel krijgt 5-10px meer ruimte. */
1125 .pat-row {
1126 grid-template-columns: 28px 1fr auto;
1127 gap: .5rem;
1128 padding: .45rem .65rem;
1129 }
1130 .pat-row .pat-num,
1131 .pat-row .pat-cover {
1132 width: 28px;
1133 height: 28px;
1134 }
1135 .pat-row::before {
1136 left: .65rem;
1137 width: 28px; height: 28px;
1138 -webkit-mask-size: 22px 22px;
1139 mask-size: 22px 22px;
1140 }
1141 .pat-row .pat-title { font-size: .92rem; }
1142 .pat-row .pat-artist { font-size: .74rem; }
1143 .pat-row .pat-duration { font-size: .74rem; }
1144
1145 /* v9.3 — Album binnen post: cover + tracks compacter */
1146 .post-album-cover {
1147 width: 90px;
1148 height: 90px;
1149 }
1150 .post-album-header {
1151 gap: .65rem;
1152 padding: .65rem;
1153 }
1154 .post-album-title { font-size: 1rem; }
1155
1156 /* v9.3 — Profile-header bovenin compacter */
1157 .profile-photo {
1158 width: 48px !important;
1159 height: 48px !important;
1160 }
1161 .profile-content {
1162 gap: .65rem;
1163 }
1164
1165 /* v9.3 — Install-app modal: minder padding, kleinere knoppen */
1166 .install-modal-inner {
1167 padding: 1rem;
1168 }
1169 .install-app-btn {
1170 padding: .55rem 1rem;
1171 font-size: .9rem;
1172 }
1173
1174 /* v9.3 — horizontaal clippen gebeurt nu globaal op html (zie de html-regel
1175 bovenaan). Hier bewust NIETS op body zetten: body als scroll-container zou
1176 de fixed bottom-tab op mobiel laten meeschuiven. */
1177}
1178
1179/* iPhone 4 / iPhone SE 1st gen / iPhone 5/5s (320px) — strakste niveau */
1180@media (max-width: 340px) {
1181 .audio-player-inner {
1182 padding: .35rem .5rem;
1183 }
1184 .audio-player-artist { display: none; }
1185 .audio-player-cover { width: 32px; height: 32px; }
1186 body.has-audio-player .pcms-main { padding-bottom: 3.6rem; }
1187 /* Expand-sheet wat strakker */
1188 .audio-sheet-panel {
1189 padding: .5rem 1rem 1.5rem;
1190 }
1191 .audio-sheet-title { font-size: 1.2rem; }
1192 .audio-sheet-artist { font-size: .9rem; }
1193 .audio-sheet-play { width: 60px; height: 60px; }
1194 .audio-sheet-play svg { width: 26px; height: 26px; }
1195 .audio-sheet-btn { width: 42px; height: 42px; }
1196 .audio-sheet-btn svg { width: 24px; height: 24px; }
1197 .audio-sheet-controls { gap: 1rem; }
1198
1199 /* v9.3 — Op iPhone 4 (320px): tracklist nog strakker */
1200 .pat-row {
1201 grid-template-columns: 26px 1fr auto;
1202 gap: .4rem;
1203 padding: .4rem .55rem;
1204 }
1205 .pat-row .pat-num,
1206 .pat-row .pat-cover {
1207 width: 26px;
1208 height: 26px;
1209 }
1210 .pat-row::before {
1211 left: .55rem;
1212 width: 26px; height: 26px;
1213 -webkit-mask-size: 20px 20px;
1214 mask-size: 20px 20px;
1215 }
1216 .pat-row .pat-artist {
1217 display: none; /* op extreem smal weglaten ten gunste van titel */
1218 }
1219 .pat-row .pat-title { font-size: .9rem; }
1220 .pat-row .pat-duration { font-size: .72rem; }
1221
1222 /* Container padding reduceren voor max content-breedte */
1223 .container {
1224 padding-inline: 1rem !important;
1225 }
1226
1227 /* Post-cover (de grote bovenste) krimpen */
1228 .post-cover {
1229 max-height: 200px;
1230 }
1231}
1232
1233/* ============================================================
1234 v9.0 — Audio player expand-sheet (Spotify-style "now playing")
1235 Slide-up half-screen met grote cover, track info, big controls
1236 ============================================================ */
1237.audio-sheet {
1238 position: fixed;
1239 inset: 0;
1240 z-index: 1100;
1241 pointer-events: none;
1242 opacity: 0;
1243 transition: opacity .25s ease;
1244}
1245.audio-sheet.is-open {
1246 pointer-events: auto;
1247 opacity: 1;
1248}
1249.audio-sheet-backdrop {
1250 position: absolute;
1251 inset: 0;
1252 /* v9.3 — Blur en overlay-dim allebei via CSS-variabele --pcms-sheet-progress
1253 (1 = volledig, 0 = weg). JS update tijdens drag; CSS-transition pakt
1254 open/close af. Sterke blur (24px) zodat 't effect goed zichtbaar is. */
1255 background: rgb(0 0 0 / calc(.4 * var(--pcms-sheet-progress, 1)));
1256 backdrop-filter: blur(calc(24px * var(--pcms-sheet-progress, 1)));
1257 -webkit-backdrop-filter: blur(calc(24px * var(--pcms-sheet-progress, 1)));
1258 transition: background .25s ease,
1259 backdrop-filter .25s ease,
1260 -webkit-backdrop-filter .25s ease;
1261 will-change: backdrop-filter, background;
1262}
1263/* Tijdens drag: instant updates vanuit JS, geen transition */
1264.audio-sheet-panel.is-dragging ~ .audio-sheet-backdrop,
1265.audio-sheet-backdrop.is-dragging {
1266 transition: none;
1267}
1268.audio-sheet-panel {
1269 position: absolute;
1270 left: 0; right: 0; bottom: 0;
1271 background: var(--paper, #fff);
1272 border-top-left-radius: 20px;
1273 border-top-right-radius: 20px;
1274 box-shadow: 0 -20px 60px rgba(0, 0, 0, .25);
1275 padding: .75rem 1.5rem 2rem;
1276 max-height: 85vh;
1277 overflow-y: auto;
1278 /* v9.2.1 — scroll blijft binnen panel, geen chaining naar body (iOS-proof) */
1279 overscroll-behavior: contain;
1280 touch-action: pan-y;
1281 /* Hide scrollbar but keep scrollable */
1282 scrollbar-width: none; /* Firefox */
1283 -ms-overflow-style: none; /* IE/Edge */
1284 transform: translateY(100%);
1285 transition: transform .3s cubic-bezier(.22, .9, .3, 1),
1286 opacity .3s cubic-bezier(.22, .9, .3, 1);
1287 display: flex;
1288 flex-direction: column;
1289 gap: 1rem;
1290 color: var(--ink);
1291}
1292.audio-sheet-panel::-webkit-scrollbar {
1293 display: none; /* Chrome/Safari */
1294}
1295/* Body scroll lock wanneer sheet open is */
1296body.audio-sheet-locked {
1297 overflow: hidden;
1298}
1299.audio-sheet.is-open .audio-sheet-panel {
1300 transform: translateY(0);
1301}
1302
1303/* v9.3 — Drag-zone: pill bovenaan + cover. Hele strook is touch-target voor
1304 swipe-down-to-close. Pull-to-refresh is uitgeschakeld op html-niveau dus
1305 geen interferentie. Onder de cover (info/progress/controls/queue) werkt
1306 normale touch — knoppen, scroll in queue, etc. */
1307.audio-sheet-drag-zone {
1308 flex-shrink: 0;
1309 display: flex;
1310 flex-direction: column;
1311 align-items: stretch;
1312 gap: 1rem;
1313 /* v9.3 — touch-action: pan-y staat verticale scroll toe (zodat queue
1314 eronder scrollt als gebruiker omhoog veegt over cover). Onze JS
1315 detecteert intent: alleen omlaag-swipe vanaf de top sluit de sheet,
1316 omhoog-swipe = scroll. */
1317 touch-action: pan-y;
1318 user-select: none;
1319 -webkit-user-select: none;
1320 cursor: grab;
1321 margin: -.75rem -1.5rem 0;
1322 padding: .75rem 1.5rem 0;
1323}
1324.audio-sheet-drag-zone:active { cursor: grabbing; }
1325
1326/* v9.4 — Drag alleen actief op touch-only apparaten (telefoons).
1327 Desktop met muis + tablets met muis-cursor → geen drag-grip,
1328 gebruiker sluit via × pill-knop bovenin of klik op backdrop. */
1329@media (hover: hover) and (pointer: fine) {
1330 .audio-sheet-drag-zone {
1331 touch-action: auto;
1332 cursor: default;
1333 pointer-events: none;
1334 }
1335 /* Pill blijft klikbaar als sluit-knop */
1336 .audio-sheet-drag-zone .audio-sheet-handle {
1337 pointer-events: auto;
1338 cursor: pointer;
1339 }
1340}
1341
1342/* Pill (handle) gecentreerd boven de cover */
1343.audio-sheet-drag-zone .audio-sheet-handle {
1344 margin: 0 auto .25rem;
1345}
1346
1347/* Tijdens dragging: panel volgt vinger realtime; geen transition */
1348.audio-sheet-panel.is-dragging {
1349 transition: none;
1350 will-change: transform;
1351}
1352[data-theme="dark"] .audio-sheet-panel {
1353 background: var(--paper, #1a1a1a);
1354 box-shadow: 0 -20px 60px rgba(0, 0, 0, .5);
1355}
1356/* Drag-handle + close button in één */
1357.audio-sheet-handle {
1358 display: block;
1359 width: 48px;
1360 height: 4px;
1361 border-radius: 2px;
1362 background: color-mix(in srgb, var(--ink, #000) 25%, transparent);
1363 border: none;
1364 margin: 0 auto .5rem;
1365 padding: 0;
1366 cursor: pointer;
1367 flex-shrink: 0;
1368 position: relative;
1369}
1370.audio-sheet-handle::before {
1371 content: "";
1372 position: absolute;
1373 /* v9.3 — Drag-strip wrapper neemt nu de hit-area-rol over. ::before
1374 blijft als kleine extra padding voor click-comfort. */
1375 inset: -10px -20px;
1376}
1377.audio-sheet-handle:hover {
1378 background: color-mix(in srgb, var(--ink, #000) 45%, transparent);
1379}
1380/* Grote cover */
1381.audio-sheet-cover {
1382 width: 100%;
1383 max-width: 360px;
1384 aspect-ratio: 1/1;
1385 margin: 0 auto;
1386 border-radius: 12px;
1387 background: linear-gradient(135deg,
1388 var(--accent, #c2410c),
1389 color-mix(in srgb, var(--accent, #c2410c) 55%, #000));
1390 background-size: cover;
1391 background-position: center;
1392 box-shadow: 0 20px 40px rgba(0, 0, 0, .15);
1393 flex-shrink: 0;
1394}
1395[data-theme="dark"] .audio-sheet-cover {
1396 box-shadow: 0 20px 40px rgba(0, 0, 0, .4);
1397}
1398.audio-sheet-info {
1399 text-align: center;
1400 padding: 0 1rem;
1401}
1402.audio-sheet-title {
1403 font-family: var(--font-display, inherit);
1404 font-size: 1.5rem;
1405 font-weight: 600;
1406 line-height: 1.2;
1407 margin: 0 0 .25rem;
1408 letter-spacing: -0.01em;
1409 color: var(--ink);
1410}
1411.audio-sheet-artist {
1412 font-size: 1rem;
1413 color: var(--ink-muted, var(--ink));
1414 opacity: .7;
1415}
1416.audio-sheet-album {
1417 margin-top: .35rem;
1418 font-size: .82rem;
1419 opacity: .5;
1420 text-transform: uppercase;
1421 letter-spacing: .05em;
1422}
1423.audio-sheet-album:empty { display: none; }
1424/* Progress + time */
1425.audio-sheet-progress {
1426 display: grid;
1427 grid-template-columns: auto 1fr auto;
1428 gap: .6rem;
1429 align-items: center;
1430 padding: 0 .5rem;
1431}
1432.audio-sheet-progress .audio-seek { width: 100%; }
1433.audio-sheet-progress .audio-time {
1434 font-size: .78rem;
1435 opacity: .55;
1436}
1437/* Grote controls */
1438.audio-sheet-controls {
1439 display: flex;
1440 align-items: center;
1441 justify-content: center;
1442 gap: 1.75rem;
1443}
1444.audio-sheet-btn {
1445 width: 48px;
1446 height: 48px;
1447 padding: 0;
1448}
1449.audio-sheet-btn svg { width: 28px; height: 28px; }
1450.audio-sheet-play {
1451 width: 72px;
1452 height: 72px;
1453 border-radius: 50%;
1454 background: var(--accent, #c2410c);
1455 color: var(--paper, #fff);
1456 border: none;
1457 cursor: pointer;
1458 display: inline-flex;
1459 align-items: center;
1460 justify-content: center;
1461 transition: transform .1s;
1462}
1463.audio-sheet-play:hover { transform: scale(1.05); }
1464.audio-sheet-play:active { transform: scale(.95); }
1465.audio-sheet-play svg { width: 30px; height: 30px; }
1466.audio-sheet-play .icon-pause { display: none; }
1467/* v9.2.1 — sheet staat nu als sibling van .audio-player buiten de balk,
1468 dus ancestor-selector .audio-player.is-playing werkt niet meer voor de
1469 sheet. JS zet is-playing ook rechtstreeks op sheet.play (regel 551 app.js). */
1470.audio-sheet-play.is-playing .icon-play { display: none; }
1471.audio-sheet-play.is-playing .icon-pause { display: block; }
1472/* v9.2.1 — fallback: als sheet buiten alle ancestors zit, tag body */
1473body.audio-is-playing .audio-sheet-play .icon-play { display: none; }
1474body.audio-is-playing .audio-sheet-play .icon-pause { display: block; }
1475
1476/* v9.3 — Loading state: roterende spiraal (het roboburr logo).
1477 Button-achtergrond wordt transparant, play/pause svgs verbergen, en de
1478 spiraal verschijnt als roterende background via ::after pseudo-element.
1479 Cool-effect: zachte hue-drift geeft de kleur een levend gevoel. */
1480.audio-player.is-loading .audio-btn-play,
1481.audio-player.is-loading .audio-sheet-play,
1482body.audio-is-loading .audio-sheet-play,
1483.pat-row.is-loading {
1484 pointer-events: none;
1485}
1486.audio-player.is-loading .audio-btn-play,
1487.audio-player.is-loading .audio-sheet-play,
1488body.audio-is-loading .audio-sheet-play {
1489 background: transparent;
1490 box-shadow: none;
1491}
1492
1493/* v9.3 — Play/pause-icons in de player-knoppen faden smooth uit/in tijdens
1494 loading. Pseudo-spiraal faded tegelijkertijd in (geen instant pop). */
1495.audio-btn-play > svg,
1496.audio-sheet-play > svg {
1497 transition: opacity .35s cubic-bezier(.4, 0, .2, 1),
1498 transform .35s cubic-bezier(.4, 0, .2, 1);
1499}
1500.audio-player.is-loading .audio-btn-play > svg,
1501.audio-player.is-loading .audio-sheet-play > svg,
1502body.audio-is-loading .audio-sheet-play > svg {
1503 opacity: 0;
1504 transform: scale(.7);
1505}
1506.pat-row.is-loading .pat-play-icon > svg,
1507.pat-row.is-loading .pat-num,
1508.pat-row.is-loading .pat-cover {
1509 opacity: 0;
1510}
1511
1512/* v9.3 — Spiraal als pseudo-element, ALTIJD aanwezig met opacity 0 default.
1513 Bij is-loading faden 'ie smooth in (opacity + scale-bounce), bij klaar
1514 faden 'ie weer uit. Pure accent-kleur, geen hue-drift. */
1515.audio-player .audio-btn-play,
1516.audio-player .audio-sheet-play,
1517.pat-row .pat-play-icon {
1518 position: relative;
1519}
1520.audio-btn-play::after,
1521.audio-sheet-play::after {
1522 content: "";
1523 position: absolute;
1524 inset: 0;
1525 background-color: var(--accent, #c2410c);
1526 -webkit-mask: url('/assets/spinner.svg') center/contain no-repeat;
1527 mask: url('/assets/spinner.svg') center/contain no-repeat;
1528 opacity: 0;
1529 transform: scale(.6);
1530 transition: opacity .4s cubic-bezier(.4, 0, .2, 1),
1531 transform .4s cubic-bezier(.34, 1.56, .64, 1);
1532 pointer-events: none;
1533 animation: pcms-spiral-spin 1.2s linear infinite paused;
1534 will-change: opacity, transform;
1535}
1536.audio-player.is-loading .audio-btn-play::after,
1537.audio-player.is-loading .audio-sheet-play::after,
1538body.audio-is-loading .audio-sheet-play::after {
1539 opacity: 1;
1540 transform: scale(1);
1541 animation-play-state: running;
1542}
1543/* Pat-row keeps its existing ::before spinner from earlier change.
1544 Voor backward-compat als oude HTML nog .pat-play-icon::after spinner had */
1545.pat-row.is-loading .pat-play-icon::after {
1546 content: "";
1547 position: absolute;
1548 inset: 0;
1549 background-color: var(--accent, #c2410c);
1550 -webkit-mask: url('/assets/spinner.svg') center/contain no-repeat;
1551 mask: url('/assets/spinner.svg') center/contain no-repeat;
1552 opacity: 1;
1553 animation: pcms-spiral-spin 1.2s linear infinite;
1554 pointer-events: none;
1555}
1556@keyframes pcms-spiral-spin {
1557 to { transform: scale(1) rotate(-360deg); }
1558}
1559/* Queue list */
1560.audio-sheet-queue {
1561 margin-top: .5rem;
1562 padding-top: 1rem;
1563 border-top: 1px solid var(--rule);
1564}
1565.audio-sheet-queue-label {
1566 font-size: .75rem;
1567 text-transform: uppercase;
1568 letter-spacing: .08em;
1569 opacity: .5;
1570 font-weight: 600;
1571 margin-bottom: .5rem;
1572 padding: 0 .5rem;
1573}
1574.audio-sheet-queue-list {
1575 list-style: none;
1576 padding: 0;
1577 margin: 0;
1578 display: flex;
1579 flex-direction: column;
1580 gap: 2px;
1581}
1582.audio-sheet-queue-item {
1583 display: flex;
1584 align-items: center;
1585 gap: .75rem;
1586 padding: .5rem .6rem;
1587 border-radius: 6px;
1588 cursor: pointer;
1589 transition: background .15s;
1590 background: none;
1591 border: none;
1592 width: 100%;
1593 color: inherit;
1594 font: inherit;
1595 text-align: left;
1596}
1597.audio-sheet-queue-item:hover {
1598 background: color-mix(in srgb, var(--ink, #000) 6%, transparent);
1599}
1600.audio-sheet-queue-item.is-current {
1601 background: color-mix(in srgb, var(--accent, #c2410c) 14%, transparent);
1602 color: var(--accent, #c2410c);
1603}
1604.audio-sheet-queue-cover {
1605 width: 36px;
1606 height: 36px;
1607 border-radius: 4px;
1608 background-size: cover;
1609 background-position: center;
1610 background-color: var(--rule);
1611 flex-shrink: 0;
1612}
1613.audio-sheet-queue-meta {
1614 flex: 1;
1615 min-width: 0;
1616 display: flex;
1617 flex-direction: column;
1618}
1619.audio-sheet-queue-title {
1620 font-size: .9rem;
1621 font-weight: 500;
1622 overflow: hidden;
1623 text-overflow: ellipsis;
1624 white-space: nowrap;
1625}
1626.audio-sheet-queue-artist {
1627 font-size: .75rem;
1628 opacity: .55;
1629 overflow: hidden;
1630 text-overflow: ellipsis;
1631 white-space: nowrap;
1632}
1633.audio-sheet-queue-duration {
1634 font-family: ui-monospace, monospace;
1635 font-size: .72rem;
1636 opacity: .5;
1637 flex-shrink: 0;
1638}
1639
1640/* Desktop: sheet is max 480px wide and centered for bigger screens */
1641@media (min-width: 720px) {
1642 .audio-sheet-panel {
1643 left: 50%;
1644 right: auto;
1645 width: 480px;
1646 transform: translate(-50%, 100%);
1647 border-top-left-radius: 20px;
1648 border-top-right-radius: 20px;
1649 }
1650 .audio-sheet.is-open .audio-sheet-panel {
1651 transform: translate(-50%, 0);
1652 }
1653}
1654
1655/* v9.2.1 — Mobiel: sheet is fullscreen, alleen te sluiten via handle-knop bovenin.
1656 Geen rounded corners, volledige viewport, safe-area voor notches/status bar. */
1657@media (max-width: 719.98px) {
1658 .audio-sheet-panel {
1659 inset: 0;
1660 max-height: none;
1661 border-top-left-radius: 0;
1662 border-top-right-radius: 0;
1663 box-shadow: none;
1664 padding-top: calc(.75rem + var(--ios-safe-top, 0px));
1665 padding-bottom: calc(2rem + env(safe-area-inset-bottom, 0px));
1666 }
1667 /* v9.3 — Backdrop blijft visible op mobile zodat drag-gesture de blur
1668 laat doorschemeren naar helder. */
1669}
1670
1671/* ============================================================
1672 Mobile masthead + pagination
1673 ============================================================ */
1674@media (max-width: 600px) {
1675 .masthead-inner { gap: .35rem; }
1676 .site-title { font-size: 1.2rem; }
1677 .site-subtitle { display: none; }
1678 .top-nav { gap: .1rem; }
1679 .nav-label { display: none; }
1680 .nav-btn, .nav-link {
1681 padding: .4rem .45rem;
1682 min-width: 38px;
1683 justify-content: center;
1684 }
1685 .pagination { flex-direction: column; gap: .5rem; }
1686 .pagination-item { width: 100%; }
1687}
1688
1689/* Taal-keuze in de header-nav (NL/EN/DE) — eigen gestylede dropdown. */
1690.lang-menu { position: relative; }
1691.lang-menu > summary {
1692 list-style: none; cursor: pointer;
1693 display: inline-flex; align-items: center; gap: .3rem;
1694 padding: .35rem .55rem; border-radius: 999px;
1695 border: 1px solid var(--rule); background: transparent; color: var(--ink);
1696}
1697.lang-menu > summary::-webkit-details-marker { display: none; }
1698.lang-menu > summary:hover { border-color: var(--accent); }
1699.lang-toggle .lang-code { font-size: .8rem; font-weight: 700; letter-spacing: .02em; }
1700.lang-toggle .icon { width: 16px; height: 16px; opacity: .8; }
1701.lang-caret { width: 12px; height: 12px; opacity: .7; transition: transform .15s; }
1702.lang-menu[open] .lang-caret { transform: rotate(180deg); }
1703.lang-dropdown {
1704 position: absolute; top: calc(100% + 8px); right: 0;
1705 min-width: 170px; z-index: 60;
1706 background: var(--paper); border: 1px solid var(--rule);
1707 border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,.22);
1708 padding: .35rem; display: flex; flex-direction: column;
1709}
1710.lang-item {
1711 display: flex; align-items: center; gap: .6rem;
1712 padding: .5rem .65rem; border-radius: 8px;
1713 color: var(--ink); text-decoration: none; font-size: .9rem;
1714}
1715.lang-item:hover { background: var(--paper-2); }
1716.lang-item.is-active { color: var(--accent); font-weight: 600; }
1717.lang-item-code {
1718 font-size: .7rem; font-weight: 700; opacity: .6;
1719 min-width: 1.6em;
1720}
1721@media (max-width: 400px) {
1722 .masthead { padding: calc(.5rem + var(--ios-safe-top, 0px)) 0 .5rem; }
1723 .masthead-inner { gap: .25rem; }
1724 .site-title { font-size: 1.05rem; }
1725 .nav-btn, .nav-link {
1726 padding: .35rem .3rem;
1727 min-width: 34px;
1728 }
1729 .nav-btn .icon, .nav-link .icon { width: 1rem; height: 1rem; }
1730 /* PWA-install knop verbergen op klein scherm — kan ook via menu */
1731 .nav-install-btn { display: none !important; }
1732}
1733@media (max-width: 340px) {
1734 .site-title { font-size: .95rem; }
1735 .nav-btn, .nav-link { padding: .3rem .25rem; min-width: 30px; }
1736 /* Theme-toggle verbergen op ultra-klein — kan via user-menu */
1737 [data-pcms-theme-toggle] { display: none; }
1738}
1739
1740.post-date-ago {
1741 margin-left: .5em;
1742 opacity: .6;
1743 font-size: .9em;
1744 font-style: italic;
1745 text-transform: none;
1746 letter-spacing: 0;
1747}
1748
1749/* HTMX loading indicator — subtle progress-bar aan de top van de content */
1750.pcms-loading {
1751 position: fixed;
1752 top: 0; left: 0;
1753 height: 2px;
1754 width: 0%;
1755 background: var(--accent, #c2410c);
1756 z-index: 9999;
1757 transition: width .3s ease, opacity .2s;
1758 opacity: 0;
1759 pointer-events: none;
1760}
1761.pcms-loading.htmx-request {
1762 opacity: 1;
1763 width: 80%;
1764 transition: width 6s cubic-bezier(.1,.9,.2,1), opacity .2s;
1765}
1766/* subtile fade wanneer content gewisseld wordt */
1767#pcms-main.htmx-swapping {
1768 opacity: .5;
1769 transition: opacity .15s;
1770}
1771
1772/* Masthead brand group (site-title + optional tagline) */
1773.masthead-brand { display: flex; flex-direction: column; gap: 2px; }
1774.site-subtitle {
1775 font-family: var(--font-ui, inherit);
1776 font-size: .75rem;
1777 color: var(--ink-muted, rgba(0,0,0,.55));
1778 letter-spacing: 0;
1779 line-height: 1.3;
1780}
1781
1782/* ============================================================
1783 v7.3 — TAGS, TYPE, ARCHIEF, ZOEK, RELATED, SPECIAL VIEWS
1784 ============================================================ */
1785
1786/* Post-meta row — datum + type-chip + tags samen onder de titel */
1787.post-meta {
1788 display: flex;
1789 flex-wrap: wrap;
1790 align-items: center;
1791 gap: .5rem .85rem;
1792 margin-top: .5rem;
1793}
1794.post-meta .post-date { margin: 0; }
1795
1796/* Type-chip (groter, als een label) */
1797.post-type-chip {
1798 display: inline-flex;
1799 align-items: center;
1800 padding: .2rem .6rem;
1801 background: color-mix(in srgb, var(--accent) 10%, transparent);
1802 color: var(--accent);
1803 border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
1804 border-radius: 999px;
1805 font-family: var(--font-ui);
1806 font-size: .72rem;
1807 font-weight: 600;
1808 text-decoration: none;
1809 letter-spacing: .04em;
1810 text-transform: uppercase;
1811 transition: background .15s;
1812}
1813.post-type-chip:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
1814
1815/* Tag-chips — klein, subtiel, gelinkt */
1816.post-tags, .post-list-tags {
1817 display: inline-flex;
1818 flex-wrap: wrap;
1819 gap: .3rem;
1820}
1821.tag-chip {
1822 display: inline-block;
1823 padding: .15rem .55rem;
1824 background: color-mix(in srgb, var(--ink) 5%, transparent);
1825 color: var(--ink-muted);
1826 border-radius: 999px;
1827 font-family: var(--font-ui);
1828 font-size: .72rem;
1829 font-weight: 500;
1830 text-decoration: none;
1831 transition: background .15s, color .15s;
1832}
1833.tag-chip:hover {
1834 background: color-mix(in srgb, var(--accent) 12%, transparent);
1835 color: var(--accent);
1836}
1837
1838/* ============================================================
1839 SPECIAL PAGES (archief, tag, type, zoek)
1840 ============================================================ */
1841.special-page .post-header { margin-bottom: 2rem; }
1842.special-eyebrow {
1843 font-size: .72rem;
1844 color: var(--ink-muted);
1845 text-transform: uppercase;
1846 letter-spacing: .12em;
1847 margin: 0 0 .25rem;
1848}
1849
1850/* Archief: jaar-overzicht */
1851.archive-years {
1852 display: flex;
1853 flex-direction: column;
1854 gap: 2rem;
1855}
1856.archive-year h2 {
1857 font-family: var(--font-display);
1858 font-size: 1.75rem;
1859 margin: 0 0 .75rem;
1860}
1861.archive-year h2 a {
1862 color: var(--ink);
1863 text-decoration: none;
1864}
1865.archive-year h2 a:hover { color: var(--accent); }
1866.archive-year h2 .admin-muted { font-size: .9rem; font-weight: normal; color: var(--ink-muted); }
1867.archive-months {
1868 list-style: none;
1869 padding: 0; margin: 0;
1870 display: grid;
1871 grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
1872 gap: .5rem;
1873}
1874.archive-months li {
1875 display: flex;
1876 align-items: center;
1877 gap: .4rem;
1878 padding: .55rem .75rem;
1879 background: color-mix(in srgb, var(--ink) 3%, transparent);
1880 border-radius: var(--radius);
1881 transition: background .15s;
1882}
1883.archive-months li:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
1884.archive-months a {
1885 color: var(--ink);
1886 text-decoration: none;
1887 font-weight: 500;
1888 font-size: .95rem;
1889}
1890.archive-months .admin-muted { font-size: .75rem; color: var(--ink-muted); margin-left: auto; }
1891
1892/* Archief: jaar drill-down */
1893.archive-month-list {
1894 display: flex;
1895 flex-direction: column;
1896 gap: 2rem;
1897}
1898.archive-month h2 {
1899 font-family: var(--font-display);
1900 font-size: 1.35rem;
1901 margin: 0 0 .5rem;
1902 padding-bottom: .35rem;
1903 border-bottom: 1px solid var(--rule);
1904}
1905.archive-month h2 a {
1906 color: var(--ink);
1907 text-decoration: none;
1908}
1909.archive-month h2 a:hover { color: var(--accent); }
1910
1911/* Compact post-list (gebruikt in archief drill-down per maand) */
1912.post-compact-list {
1913 list-style: none;
1914 padding: 0; margin: 0;
1915 display: flex;
1916 flex-direction: column;
1917}
1918.post-compact-list li {
1919 border-bottom: 1px solid var(--rule);
1920}
1921.post-compact-list li:last-child { border-bottom: none; }
1922.post-compact-list a {
1923 display: grid;
1924 grid-template-columns: 3em 1fr;
1925 gap: .75rem;
1926 padding: .6rem .2rem;
1927 text-decoration: none;
1928 color: var(--ink);
1929 transition: background .12s;
1930 border-radius: 4px;
1931}
1932.post-compact-list a:hover {
1933 background: color-mix(in srgb, var(--accent) 6%, transparent);
1934}
1935.post-compact-date {
1936 color: var(--ink-muted);
1937 font-size: .8rem;
1938 align-self: center;
1939}
1940.post-compact-title { font-weight: 500; font-size: 1rem; align-self: center; }
1941.post-compact-list.large a { grid-template-columns: 4em 1fr; padding: .8rem .3rem; }
1942.post-compact-list.large .post-compact-title { font-family: var(--font-display); font-size: 1.15rem; }
1943.post-compact-excerpt {
1944 grid-column: 2;
1945 color: var(--ink-muted);
1946 font-size: .88rem;
1947 line-height: 1.5;
1948}
1949
1950/* Post-list (gebruikt in tag / type / zoek pagina's) */
1951.post-list {
1952 list-style: none;
1953 padding: 0; margin: 0;
1954 display: flex;
1955 flex-direction: column;
1956 gap: 1.5rem;
1957}
1958.post-list-item {
1959 display: grid;
1960 grid-template-columns: 120px 1fr;
1961 gap: 1.25rem;
1962 padding-bottom: 1.5rem;
1963 border-bottom: 1px solid var(--rule);
1964}
1965.post-list-item:last-child { border-bottom: none; }
1966.post-list-item:has(> .post-list-cover + .post-list-body) { grid-template-columns: 120px 1fr; }
1967.post-list-item:not(:has(.post-list-cover)) { grid-template-columns: 1fr; }
1968.post-list-cover {
1969 display: block;
1970 aspect-ratio: 1;
1971 overflow: hidden;
1972 border-radius: var(--radius);
1973 /* Accent-gradient placeholder while the cover image loads (image fades in over it). */
1974 background-image: linear-gradient(135deg,
1975 color-mix(in srgb, var(--accent, #888) 22%, var(--paper-2, var(--paper))) 0%,
1976 color-mix(in srgb, var(--accent, #888) 6%, var(--paper-2, var(--paper))) 100%);
1977}
1978.post-list-cover img, .post-list-cover video {
1979 width: 100%; height: 100%;
1980 object-fit: cover; /* fill the square, keep aspect, crop the overflow, centered */
1981 object-position: center;
1982 display: block;
1983 background-color: #fff; /* transparent logos sit on white once loaded */
1984 transition: opacity .4s ease;
1985}
1986.post-list-cover img.is-loading { opacity: 0; }
1987.post-list-body { display: flex; flex-direction: column; gap: .35rem; }
1988.post-list-meta {
1989 color: var(--ink-muted);
1990 font-size: .75rem;
1991 display: flex; gap: .35rem; align-items: center;
1992}
1993.post-list-title {
1994 font-family: var(--font-display);
1995 font-size: 1.3rem;
1996 font-weight: 450;
1997 margin: 0;
1998 line-height: 1.2;
1999}
2000.post-list-title a {
2001 color: var(--ink);
2002 text-decoration: none;
2003}
2004.post-list-title a:hover { color: var(--accent); }
2005.post-list-excerpt {
2006 color: var(--ink-muted);
2007 font-size: .95rem;
2008 margin: 0;
2009 line-height: 1.5;
2010}
2011
2012/* Zoek-formulier binnen special view */
2013.search-form {
2014 display: flex;
2015 gap: .5rem;
2016 margin-bottom: 2rem;
2017}
2018.search-form input[type=search] {
2019 flex: 1;
2020 padding: .75rem 1rem;
2021 background: var(--paper-2);
2022 border: 1px solid var(--rule);
2023 border-radius: var(--radius);
2024 font: inherit;
2025 color: var(--ink);
2026}
2027.search-form input[type=search]:focus {
2028 outline: none;
2029 border-color: var(--accent);
2030 box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);
2031}
2032
2033/* ============================================================
2034 SEARCH OVERLAY (masthead → full-screen zoekbalk)
2035 ============================================================ */
2036.search-overlay {
2037 position: fixed;
2038 inset: 0;
2039 background: color-mix(in srgb, var(--ink) 50%, transparent);
2040 z-index: 1500;
2041 display: flex;
2042 justify-content: center;
2043 align-items: flex-start;
2044 padding-top: 10vh;
2045 backdrop-filter: blur(6px);
2046 -webkit-backdrop-filter: blur(6px);
2047}
2048.search-overlay[hidden] { display: none; }
2049.search-overlay-form {
2050 width: min(90vw, 600px);
2051 background: var(--paper);
2052 border-radius: calc(var(--radius) * 1.5);
2053 padding: .75rem 1rem;
2054 display: flex;
2055 align-items: center;
2056 gap: .6rem;
2057 box-shadow: 0 20px 60px rgba(0,0,0,.3);
2058 border: 1px solid var(--rule);
2059}
2060.search-overlay-form .icon {
2061 width: 1.2rem; height: 1.2rem;
2062 color: var(--ink-muted);
2063 flex-shrink: 0;
2064}
2065.search-overlay-form input[type=search] {
2066 flex: 1;
2067 background: transparent;
2068 border: none;
2069 font-family: var(--font-body);
2070 font-size: 1.1rem;
2071 color: var(--ink);
2072 padding: .5rem 0;
2073}
2074.search-overlay-form input[type=search]:focus { outline: none; }
2075.search-overlay-form .nav-btn {
2076 background: transparent;
2077 border: none;
2078 color: var(--ink-muted);
2079 cursor: pointer;
2080 font-size: 1.25rem;
2081 line-height: 1;
2082 padding: .3rem .5rem;
2083}
2084.search-overlay-form .nav-btn:hover { color: var(--ink); }
2085body.search-open { overflow: hidden; }
2086
2087/* ============================================================
2088 RELATED POSTS (onder elke post-view)
2089 ============================================================ */
2090.related-posts {
2091 margin-top: 2.5rem;
2092 padding-top: 2rem;
2093 border-top: 1px solid var(--rule);
2094}
2095.related-title {
2096 font-family: var(--font-mono);
2097 font-size: .7rem;
2098 color: var(--ink-muted);
2099 text-transform: uppercase;
2100 letter-spacing: .12em;
2101 margin: 0 0 1rem;
2102}
2103.related-grid {
2104 list-style: none;
2105 padding: 0; margin: 0;
2106 display: grid;
2107 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
2108 gap: 1rem;
2109}
2110.related-grid a {
2111 display: flex;
2112 flex-direction: column;
2113 gap: .5rem;
2114 text-decoration: none;
2115 color: var(--ink);
2116 border: 1px solid var(--rule);
2117 border-radius: var(--radius);
2118 overflow: hidden;
2119 transition: border-color .15s, transform .15s;
2120 height: 100%;
2121}
2122.related-grid a:hover {
2123 border-color: color-mix(in srgb, var(--accent) 50%, var(--rule));
2124 transform: translateY(-2px);
2125}
2126.related-cover {
2127 display: block;
2128 aspect-ratio: 16/10;
2129 background-size: cover;
2130 background-position: center;
2131 background-color: var(--paper-2);
2132}
2133
2134/* v9.4 — Wanneer related-cover ook .grid-tile-gradient class heeft (lege cover
2135 fallback), erft 'ie automatisch de hue/gradient/title styling van grid-tiles.
2136 Geen aparte related-cover-gradient meer nodig. */
2137.related-body {
2138 display: flex;
2139 flex-direction: column;
2140 gap: .25rem;
2141 padding: .6rem .75rem .9rem;
2142}
2143.related-meta { color: var(--ink-muted); font-size: .7rem; }
2144.related-name {
2145 font-family: var(--font-display);
2146 font-weight: 450;
2147 font-size: 1rem;
2148 line-height: 1.25;
2149}
2150
2151/* ============================================================
2152 MOBILE TWEAKS voor v7.3
2153 ============================================================ */
2154@media (max-width: 600px) {
2155 .post-list-item { grid-template-columns: 1fr; }
2156 .post-list-cover { aspect-ratio: 16/9; }
2157 .archive-months { grid-template-columns: repeat(2, 1fr); }
2158 .related-grid { grid-template-columns: 1fr; }
2159 .search-overlay { padding-top: 4vh; }
2160}
2161
2162/* ============================================================
2163 v7.4 — PROFILE HEADER + VIEW SWITCHER + GRID + POST-TYPE LAYOUTS
2164 MOBILE-FIRST — belangrijkste eis
2165 ============================================================ */
2166
2167/* -------- PROFILE HEADER (Optie C: full op home, compact op post/special) -------- */
2168
2169.profile-header {
2170 background: var(--paper-2, var(--paper));
2171 border-bottom: 1px solid var(--rule);
2172 transition: padding .25s ease, background .2s;
2173}
2174/* Mobiel default = full-mode padding */
2175.profile-header { padding: 1.25rem 0; }
2176.profile-header-inner {
2177 display: flex;
2178 gap: .9rem;
2179 align-items: flex-start;
2180}
2181
2182.profile-photo {
2183 flex-shrink: 0;
2184 width: 80px;
2185 height: 80px;
2186 border-radius: 50%;
2187 overflow: hidden;
2188 display: block;
2189 background: var(--paper);
2190 border: 2px solid var(--rule);
2191 transition: width .25s ease, height .25s ease, border-color .2s;
2192 text-decoration: none;
2193}
2194.profile-photo:hover { border-color: var(--accent); }
2195.profile-photo img {
2196 width: 100%; height: 100%;
2197 object-fit: cover;
2198 display: block;
2199}
2200.profile-photo-fallback {
2201 display: flex;
2202 align-items: center;
2203 justify-content: center;
2204 width: 100%; height: 100%;
2205 background: var(--accent);
2206 color: var(--paper);
2207 font-family: var(--font-display);
2208 font-weight: 700;
2209 font-size: 2.2rem;
2210 text-transform: uppercase;
2211 line-height: 1;
2212 transition: font-size .25s ease;
2213}
2214
2215.profile-info {
2216 flex: 1;
2217 min-width: 0;
2218 display: flex;
2219 flex-direction: column;
2220 gap: .3rem;
2221}
2222.profile-name {
2223 margin: 0;
2224 font-family: var(--font-display);
2225 font-size: 1.2rem;
2226 font-weight: 500;
2227 line-height: 1.15;
2228 transition: font-size .25s ease;
2229}
2230.profile-name a {
2231 color: var(--ink);
2232 text-decoration: none;
2233}
2234.profile-name a:hover { color: var(--accent); }
2235.profile-bio {
2236 margin: 0;
2237 color: var(--ink-muted);
2238 font-size: .92rem;
2239 line-height: 1.45;
2240 max-height: 200px;
2241 overflow: hidden;
2242 transition: max-height .25s ease, margin .25s ease, opacity .2s;
2243}
2244.profile-links {
2245 list-style: none;
2246 padding: 0;
2247 margin: .15rem 0 0;
2248 display: flex;
2249 flex-wrap: wrap;
2250 gap: .4rem;
2251 max-height: 50px;
2252 overflow: hidden;
2253 transition: max-height .25s ease, margin .25s ease, opacity .2s;
2254}
2255.profile-links li { margin: 0; }
2256.profile-links a,
2257.profile-links .profile-fedi-link {
2258 display: inline-flex;
2259 align-items: center;
2260 justify-content: center;
2261 width: 40px;
2262 height: 40px;
2263 border-radius: 50%;
2264 background: color-mix(in srgb, var(--ink) 5%, transparent);
2265 color: var(--ink-muted);
2266 text-decoration: none;
2267 transition: background .15s, color .15s;
2268}
2269.profile-links a:hover,
2270.profile-links .profile-fedi-link:hover {
2271 background: color-mix(in srgb, var(--accent) 15%, transparent);
2272 color: var(--accent);
2273}
2274.profile-links .icon { width: 1.1rem; height: 1.1rem; }
2275
2276/* -------- COMPACT MODE: op post + special pages -------- */
2277
2278.on-post .profile-header,
2279.on-special .profile-header {
2280 padding: .5rem 0;
2281}
2282.on-post .profile-photo,
2283.on-special .profile-photo {
2284 width: 36px;
2285 height: 36px;
2286 border-width: 1px;
2287}
2288.on-post .profile-photo-fallback,
2289.on-special .profile-photo-fallback {
2290 font-size: 1rem;
2291}
2292.on-post .profile-name,
2293.on-special .profile-name {
2294 font-size: 1rem;
2295 align-self: center;
2296}
2297.on-post .profile-bio,
2298.on-special .profile-bio,
2299.on-post .profile-links,
2300.on-special .profile-links {
2301 display: none;
2302}
2303.on-post .profile-header-inner,
2304.on-special .profile-header-inner {
2305 align-items: center;
2306 justify-content: flex-start;
2307 gap: .6rem;
2308}
2309.on-post .profile-info,
2310.on-special .profile-info {
2311 flex: 0 1 auto;
2312 min-width: 0;
2313}
2314.on-post .profile-name,
2315.on-special .profile-name {
2316 text-align: left;
2317}
2318
2319/* -------- DESKTOP: meer ruimte, grotere foto -------- */
2320@media (min-width: 768px) {
2321 .profile-header { padding: 2rem 0; }
2322 .profile-photo { width: 120px; height: 120px; }
2323 .profile-photo-fallback { font-size: 3.2rem; }
2324 .profile-name { font-size: 1.5rem; }
2325 .profile-bio { font-size: 1rem; }
2326 .profile-header-inner { gap: 1.5rem; }
2327 .on-post .profile-header,
2328 .on-special .profile-header { padding: .6rem 0; }
2329 .on-post .profile-photo,
2330 .on-special .profile-photo { width: 42px; height: 42px; }
2331 /* Compact mode: gap blijft klein, ook op desktop */
2332 .on-post .profile-header-inner,
2333 .on-special .profile-header-inner { gap: .75rem; }
2334 .on-post .profile-name,
2335 .on-special .profile-name { font-size: 1.1rem; }
2336}
2337
2338/* -------- VIEW SWITCHER -------- */
2339.view-switcher-wrap {
2340 border-bottom: 1px solid var(--rule);
2341 background: var(--paper);
2342 /* Bottom margin gives breathing room between the switcher bar and the
2343 first post. margin-top staat in shared-styles.ejs (de winnende inline
2344 <style>) — symmetrisch op 1.5rem. */
2345 margin-bottom: 1.5rem;
2346}
2347.view-switcher {
2348 display: flex;
2349 justify-content: center;
2350 gap: .35rem;
2351 /* Slimmer bar — was .6rem, now .35rem so the bar reads as a divider
2352 rather than a row of weight equal to the header. */
2353 padding: .35rem 0;
2354}
2355.view-switch-btn {
2356 display: inline-flex;
2357 align-items: center;
2358 gap: .4rem;
2359 padding: .35rem .85rem; /* was .55rem 1rem */
2360 min-height: 32px; /* was 44px */
2361 background: transparent;
2362 border: 1px solid var(--rule);
2363 border-radius: 999px;
2364 color: var(--ink-muted);
2365 font-family: var(--font-ui);
2366 font-size: .82rem; /* was .85rem */
2367 cursor: pointer;
2368 transition: all .15s;
2369}
2370.view-switch-btn:hover {
2371 color: var(--ink);
2372 border-color: var(--ink-muted);
2373}
2374/* Uitgeschakeld (Lezen in de cirkel) wint van :hover -- anders licht een knop
2375 op die je niet kunt indrukken, en dat is precies de verkeerde belofte. */
2376.view-switch-btn[disabled],
2377.view-switch-btn[disabled]:hover {
2378 opacity: .38;
2379 cursor: not-allowed;
2380 color: var(--ink-muted);
2381 border-color: var(--rule);
2382}
2383/* Actieve state: puur afgeleid van body[data-feed-view]. Geen .is-active class meer.
2384 Niet op de Archive-pagina: daar is geen "huidige" timeline/grid-keuze, dus beide
2385 knoppen blijven neutraal (grijs). */
2386/* Actieve Tijdlijn/Grid-state wordt nu gestuurd via [aria-selected="true"] (gezet
2387 door syncAria, die óók op htmx:afterSettle draait) i.p.v. body[data-feed-view].
2388 Reden: body-class/attribuut-CSS pakte niet betrouwbaar na een htmx-OOB-swap;
2389 een element-attribuut wel. De witte active-regel staat in shared-styles. */
2390.view-switch-btn .icon { width: 1rem; height: 1rem; }
2391
2392/* -------- FEED TOGGLE VIA BODY --------
2393 Grid-modus werkt op de feed (home, cirkel). Het ARCHIEF negeert de grid-keuze
2394 bewust: dat is altijd de chronologische jaar/maand-lijst (de switcher is daar
2395 grijs en springt bij klik terug naar de feed). Post-pagina's tonen de
2396 feed-timeline article sowieso altijd. Alle andere body-classes negeren
2397 data-feed-view en houden timeline visible. */
2398body.on-home[data-feed-view="grid"] .feed-timeline,
2399body.on-home[data-feed-view="grid"] .pagination,
2400body.on-home[data-feed-view="grid"] .related-posts,
2401body.on-home[data-feed-view="grid"] .article-footer,
2402body.on-cirkel[data-feed-view="grid"] .feed-timeline {
2403 display: none !important;
2404}
2405/* Grid-sectie alleen zichtbaar op de feed in grid-mode (NIET op archief) */
2406.feed-grid { display: none; }
2407body.on-home[data-feed-view="grid"] .feed-grid,
2408body.on-cirkel[data-feed-view="grid"] .feed-grid { display: block; }
2409
2410/* -------- LEESWEERGAVE (data-feed-view="reader") --------
2411 Dezelfde berichten als de tijdlijn, maar heel: één per scherm, grenzen door
2412 scroll-snapping. GEEN eigen route en geen eigen shell -- de balken blijven
2413 staan, want je bent nog op de feed en moet terug kunnen schakelen.
2414 Pagina's zonder .feed-reader (cirkel, archief, post) negeren de keuze en
2415 houden hun tijdlijn: er is hieronder simpelweg geen regel die die daar
2416 verbergt. Zo is Lezen nooit een leeg scherm. */
2417.feed-reader { display: none; }
2418body.on-home[data-feed-view="reader"] .feed-reader { display: block; }
2419/* :has(.feed-reader) is hier de LEGE STAAT, niet een truc. Zonder berichten
2420 rendert de leessectie niet, en dan mag de tijdlijn niet verborgen worden --
2421 want dáár staat "nog niets geschreven" met de knop om te beginnen. Zonder deze
2422 voorwaarde is Lezen op een verse site een wit scherm. Hetzelfde geldt voor
2423 feeds die (nog) geen leessectie hebben. */
2424body.on-home[data-feed-view="reader"]:has(.feed-reader) .feed-timeline,
2425body.on-home[data-feed-view="reader"]:has(.feed-reader) .feed-grid,
2426body.on-home[data-feed-view="reader"]:has(.feed-reader) .pagination,
2427body.on-home[data-feed-view="reader"]:has(.feed-reader) .related-posts,
2428body.on-home[data-feed-view="reader"]:has(.feed-reader) .article-footer {
2429 display: none !important;
2430}
2431
2432/* Snappen doet de SCROLLCONTAINER, en dat is het document -- niet .read-stream,
2433 die heeft overflow: visible en scrollt zelf niet. Proximity en geen mandatory:
2434 in een bericht dat langer is dan het scherm moet je rustig door kunnen lezen. */
2435html:has(body.on-home[data-feed-view="reader"]) { scroll-snap-type: y proximity; }
2436/* En de browser niet óók laten compenseren als Load more er berichten bij zet:
2437 Chrome en Firefox schuiven bij invoegen zelf mee (scroll anchoring), en dat
2438 vecht met het snappen. */
2439html:has(body.on-home[data-feed-view="reader"]),
2440.feed-reader .read-stream { overflow-anchor: none; }
2441
2442.feed-reader .read-post {
2443 scroll-snap-align: start;
2444 scroll-snap-stop: normal;
2445 min-height: 100svh;
2446 max-width: 46rem;
2447 margin: 0 auto;
2448 /* De onderrand loopt achter de vaste tabbalk door; deze padding houdt de
2449 TEKST erboven. */
2450 padding: 2rem 1.2rem 4rem;
2451 box-sizing: border-box;
2452}
2453/* Een lijn tussen twee berichten: zonder grens is een stroom een lange brij. */
2454.feed-reader .read-post + .read-post { border-top: 1px solid color-mix(in srgb, currentColor 12%, transparent); }
2455
2456.feed-reader .read-head { padding-bottom: .5rem; }
2457.feed-reader .read-title { font-size: clamp(1.6rem, 4vw, 2.4rem); line-height: 1.15; margin: 0 0 .3rem; }
2458/* De titel is een link, maar mag er niet als een link uitzien: dit is een
2459 leesscherm, geen index. */
2460.feed-reader .read-title a { color: inherit; text-decoration: none; }
2461.feed-reader .read-title a:hover,
2462.feed-reader .read-title a:focus-visible { text-decoration: underline; }
2463.feed-reader .read-when { font-size: .85rem; opacity: .6; margin: 0; }
2464
2465.feed-reader .read-foot { margin-top: 2rem; }
2466.feed-reader .read-open {
2467 display: inline-block; font-size: .9rem; opacity: .75;
2468 text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 1px;
2469}
2470.feed-reader .read-open:hover,
2471.feed-reader .read-open:focus-visible { opacity: 1; }
2472
2473@media (prefers-reduced-motion: reduce) {
2474 html:has(body.on-home[data-feed-view="reader"]) { scroll-snap-type: none; }
2475}
2476
2477/* -------- GRID VIEW TILES (Instagram-stijl) -------- */
2478.feed-grid {
2479 padding: 1rem 0 2rem;
2480}
2481.grid-tiles {
2482 display: grid;
2483 gap: 4px;
2484 grid-template-columns: repeat(2, 1fr);
2485}
2486.grid-tile {
2487 position: relative;
2488 display: block;
2489 aspect-ratio: 1;
2490 background-size: cover;
2491 background-position: center;
2492 background-color: var(--paper-2);
2493 overflow: hidden;
2494 text-decoration: none;
2495 color: var(--ink);
2496 transition: transform .2s;
2497 cursor: pointer;
2498 -webkit-tap-highlight-color: rgba(0,0,0,.1);
2499}
2500
2501/* Transparent covers (PNG logos etc.) sit on white so they don't blend into a dark
2502 theme. The white is on the IMG, so the tile's accent-gradient placeholder shows
2503 while the image is still loading. */
2504.post-cover img,
2505.post-list-cover img,
2506.grid-tile-img { background-color: #fff; }
2507/* Accent-gradient placeholder shown while the cover image loads (the image fades in
2508 over it), instead of a white flash on cover tiles. */
2509.grid-tile:not(.grid-tile-gradient) {
2510 background-image: linear-gradient(135deg,
2511 color-mix(in srgb, var(--accent, #888) 22%, var(--paper-2, var(--paper))) 0%,
2512 color-mix(in srgb, var(--accent, #888) 6%, var(--paper-2, var(--paper))) 100%);
2513}
2514/* Cover as a real <img> (not background-image): browsers downsample <img> with the
2515 high-quality image pipeline, so high-res line-art covers don't go jagged when shrunk.
2516 Fades in on load (.is-loading removed) so the placeholder shows meanwhile. */
2517.grid-tile-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; transition: opacity .4s ease; }
2518.grid-tile-img.is-loading { opacity: 0; }
2519/* Audio tile (Shaer, Robins vraag 30-7): the waveform PNG is white on
2520 transparent and floats OVER the tile's own hue gradient, so every audio
2521 post keeps its color and gets its shape. Wave and title each get their
2522 own band (wave upper, title lower): centering both stacked them right
2523 through each other (Robins schermafdruk). */
2524.grid-tile-img.grid-tile-wave {
2525 background-color: transparent;
2526 object-fit: contain;
2527 /* explicit box, not auto: an absolutely positioned img falls back to its
2528 intrinsic size when width/height are auto, collapsing the band */
2529 top: 8%; left: 8%; right: auto; bottom: auto;
2530 width: 84%; height: 46%;
2531 opacity: .85;
2532}
2533.grid-tile-audio .grid-tile-title { position: absolute; left: 10%; right: 10%; top: 60%; }
2534.grid-tile-audio .grid-tile-gradient-src { position: absolute; left: 10%; right: 10%; top: 76%; }
2535/* Cover videos are decorative, not players: let clicks + right-click pass through to the
2536 tile link so you get the normal link menu (not the browser's <video> menu/controls).
2537 Autoplay is independent of pointer-events, so the video still plays. */
2538video.grid-tile-img,
2539.post-list-cover video,
2540.post-cover video { pointer-events: none; }
2541.grid-tile:hover { transform: scale(0.98); }
2542.grid-tile-overlay {
2543 position: absolute;
2544 inset: 0;
2545 padding: .6rem;
2546 display: flex;
2547 flex-direction: column;
2548 justify-content: flex-end;
2549 align-items: flex-start;
2550 background: linear-gradient(to top, rgba(0,0,0,.65) 0%, rgba(0,0,0,0) 50%);
2551 opacity: 0;
2552 transition: opacity .2s;
2553 pointer-events: none; /* klik moet naar de <a> eronder gaan, niet naar de overlay */
2554}
2555/* Bron-site (cirkel-feed): toont bij hover "van <site>" onder de titel. */
2556/* Source label: small text that wraps to 2 lines if needed, with a big chain icon
2557 beside it (the text was 1.44rem — bigger than the title — and overflowed on mobile). */
2558.grid-tile-overlay-src {
2559 color: #fff; opacity: .85;
2560 font-size: .72rem; line-height: 1.2; margin-top: .25rem;
2561 display: flex; align-items: center; gap: .3rem; width: 100%;
2562}
2563.grid-tile-overlay-src::before { content: "⛓"; font-size: 1.3rem; line-height: 1; flex: 0 0 auto; }
2564.grid-tile-gradient-src {
2565 margin-top: .35rem; font-size: .72rem; line-height: 1.2; opacity: .85;
2566 color: var(--ink-soft);
2567 display: flex; align-items: center; gap: .3rem; width: 100%;
2568}
2569.grid-tile-gradient-src::before { content: "⛓"; font-size: 1.3rem; line-height: 1; flex: 0 0 auto; }
2570.grid-tile-overlay strong {
2571 color: #fff;
2572 font-family: var(--font-display);
2573 font-size: .9rem;
2574 font-weight: 500;
2575 line-height: 1.15;
2576 display: -webkit-box;
2577 -webkit-line-clamp: 3;
2578 -webkit-box-orient: vertical;
2579 overflow: hidden;
2580}
2581@media (hover: hover) {
2582 .grid-tile:hover .grid-tile-overlay { opacity: 1; }
2583}
2584@media (hover: none) {
2585 /* Op touch-devices altijd overlay tonen zodat titels zichtbaar zijn */
2586 .grid-tile-overlay { opacity: 1; background: linear-gradient(to top, rgba(0,0,0,.7) 0%, rgba(0,0,0,0) 70%); }
2587}
2588
2589.grid-tile-gradient {
2590 background-image: none;
2591 background-color: hsl(var(--tile-hue, 30), 40%, 85%);
2592 background-image: linear-gradient(135deg, hsl(var(--tile-hue, 30), 45%, 88%), hsl(calc(var(--tile-hue, 30) + 30), 35%, 75%));
2593 display: flex;
2594 flex-direction: column;
2595 align-items: center;
2596 justify-content: center;
2597 padding: 1rem;
2598 text-align: center;
2599}
2600[data-theme="dark"] .grid-tile-gradient,
2601.grid-tile-gradient[data-theme="dark"] {
2602 background-image: linear-gradient(135deg, hsl(var(--tile-hue, 30), 30%, 18%), hsl(calc(var(--tile-hue, 30) + 30), 25%, 12%));
2603}
2604.grid-tile-title {
2605 font-family: var(--font-display);
2606 font-size: 1rem;
2607 font-weight: 500;
2608 color: var(--ink);
2609 line-height: 1.2;
2610 display: -webkit-box;
2611 -webkit-line-clamp: 4;
2612 -webkit-box-orient: vertical;
2613 overflow: hidden;
2614 z-index: 1;
2615 /* Federated link posts can have a long bare URL as their title — break it so it wraps
2616 inside the tile and clamps cleanly instead of overflowing past both edges. */
2617 max-width: 100%;
2618 overflow-wrap: anywhere;
2619 word-break: break-word;
2620 hyphens: auto;
2621}
2622
2623.grid-tile-pin {
2624 position: absolute;
2625 top: .5rem;
2626 right: .5rem;
2627 display: inline-flex;
2628 align-items: center;
2629 gap: .25rem;
2630 padding: .2rem .55rem;
2631 background: var(--accent);
2632 color: #fff;
2633 border-radius: 999px;
2634 font-family: var(--font-ui);
2635 font-size: .65rem;
2636 font-weight: 700;
2637 text-transform: uppercase;
2638 letter-spacing: .06em;
2639 z-index: 3;
2640 box-shadow: 0 2px 6px rgba(0,0,0,.3);
2641 pointer-events: none;
2642}
2643.grid-tile-pin svg {
2644 width: .95em;
2645 height: .95em;
2646 margin-top: -1px;
2647}
2648/* Pinned/boosted tile: accent ring. An outline on the tile is painted UNDER the absolute
2649 cover <img>, so draw the ring as a pseudo-element overlay ABOVE the image (z-index above
2650 the img, below the corner badges + nsfw veil). */
2651.grid-tile.is-pinned { position: relative; z-index: 1; }
2652.grid-tile.is-pinned::after {
2653 content: '';
2654 position: absolute;
2655 inset: 0;
2656 border: 3px solid var(--accent);
2657 border-radius: inherit;
2658 pointer-events: none;
2659 z-index: 1;
2660}
2661.grid-tile-type {
2662 position: absolute;
2663 top: .4rem;
2664 left: .4rem;
2665 padding: .15rem .5rem;
2666 background: rgba(0,0,0,.55);
2667 color: #fff;
2668 border-radius: 999px;
2669 font-family: var(--font-ui);
2670 font-size: .6rem;
2671 font-weight: 600;
2672 text-transform: uppercase;
2673 letter-spacing: .05em;
2674 z-index: 2;
2675}
2676
2677@media (min-width: 600px) {
2678 .grid-tiles { grid-template-columns: repeat(3, 1fr); }
2679}
2680@media (min-width: 900px) {
2681 .grid-tiles { grid-template-columns: repeat(3, 1fr); gap: 8px; }
2682}
2683
2684/* -------- POST-TYPE SPECIFIEKE LAYOUTS -------- */
2685
2686/* Foto-post: beeld prominent, geen titel bovenaan, caption onder */
2687.feed-timeline[data-post-type="foto"] .post-title {
2688 font-size: 1.1rem;
2689 color: var(--ink-muted);
2690 font-weight: 400;
2691}
2692.feed-timeline[data-post-type="foto"] .post-cover {
2693 margin: 0 -1rem 1rem;
2694 border-radius: 0;
2695}
2696.feed-timeline[data-post-type="foto"] .post-cover img {
2697 width: 100%;
2698 border-radius: 0;
2699}
2700
2701/* Post-caption onder de cover */
2702.post-caption {
2703 font-family: var(--font-body);
2704 font-size: 1rem;
2705 color: var(--ink);
2706 line-height: 1.5;
2707 margin: 0 0 1.25rem;
2708 padding: 0 0 1rem;
2709 border-bottom: 1px solid var(--rule);
2710 white-space: pre-wrap;
2711}
2712.feed-timeline[data-post-type="foto"] .post-caption {
2713 font-size: 1.05rem;
2714 margin-top: -.5rem;
2715 padding-bottom: 1.25rem;
2716}
2717
2718/* Audio/video posts — type-chip helder, content eronder zoals normaal */
2719.feed-timeline[data-post-type="audio"] .post-title,
2720.feed-timeline[data-post-type="video"] .post-title {
2721 font-size: 1.5rem;
2722}
2723
2724@media (min-width: 768px) {
2725 .feed-timeline[data-post-type="foto"] .post-cover {
2726 margin: 0 0 1.5rem;
2727 border-radius: var(--radius);
2728 }
2729}
2730
2731/* -------- ADMIN EDIT-BUTTON op post-view (alleen zichtbaar voor ingelogde admin) -------- */
2732.post-edit-btn {
2733 position: absolute;
2734 top: 1rem;
2735 right: 1rem;
2736 display: inline-flex;
2737 align-items: center;
2738 justify-content: center;
2739 width: 44px;
2740 height: 44px;
2741 background: var(--paper);
2742 border: 1px solid var(--rule);
2743 border-radius: 50%;
2744 color: var(--ink-muted);
2745 text-decoration: none;
2746 box-shadow: 0 2px 8px rgba(0,0,0,.08);
2747 transition: background .15s, color .15s, transform .15s, border-color .15s;
2748 z-index: 10;
2749}
2750.post-edit-btn:hover {
2751 background: var(--accent);
2752 border-color: var(--accent);
2753 color: var(--paper);
2754 transform: scale(1.05);
2755}
2756.post-edit-btn .icon {
2757 width: 1.1rem;
2758 height: 1.1rem;
2759}
2760/* Zorg dat de article relative is zodat absolute positionering werkt */
2761.feed-timeline { position: relative; }
2762
2763@media (min-width: 768px) {
2764 .post-edit-btn {
2765 top: 1.5rem;
2766 right: 1.5rem;
2767 }
2768}
2769
2770/* ============================================================
2771 v8.0 — ACCENT SPAN + POST-TABLE (published posts)
2772 ============================================================ */
2773.post span.accent,
2774.post-content span.accent,
2775article span.accent,
2776page-container span.accent {
2777 color: var(--accent);
2778 font-weight: 500;
2779}
2780
2781.post-table,
2782article table.post-table {
2783 width: 100%;
2784 max-width: 100%;
2785 border-collapse: collapse;
2786 margin: 1.25rem 0;
2787 font-size: .95rem;
2788 display: block;
2789 overflow-x: auto;
2790 -webkit-overflow-scrolling: touch;
2791}
2792.post-table thead { background: color-mix(in srgb, var(--accent) 10%, transparent); }
2793.post-table th,
2794.post-table td {
2795 padding: .6rem .8rem;
2796 text-align: left;
2797 border: 1px solid var(--rule);
2798 vertical-align: top;
2799}
2800.post-table th {
2801 font-family: var(--font-ui);
2802 font-weight: 600;
2803 font-size: .88rem;
2804 color: var(--ink);
2805 letter-spacing: .02em;
2806}
2807.post-table tbody tr:nth-child(even) {
2808 background: color-mix(in srgb, var(--ink) 3%, transparent);
2809}
2810@media (min-width: 700px) {
2811 .post-table { display: table; overflow: visible; }
2812}
2813
2814/* ============================================================
2815 v8.0 fix — grid-cols picker (desktop only) + grid col overrides
2816 ============================================================ */
2817
2818/* Switcher-wrap bevat nu ook de cols-picker; layout side-by-side */
2819.view-switcher-wrap .container {
2820 display: flex;
2821 align-items: center;
2822 justify-content: center;
2823 gap: 1rem;
2824 flex-wrap: wrap;
2825}
2826
2827/* Solo / Cirkel scope-switcher (alleen in circle-modus) — segmented toggle, centraal.
2828 Hoge specificiteit (+ !important op tekst) zodat 'ie globale link-stijlen wint. */
2829.view-switcher-wrap .feed-scope {
2830 display: inline-flex;
2831 background: var(--paper-2);
2832 border: 1px solid var(--rule);
2833 border-radius: 999px;
2834 padding: 3px;
2835}
2836.view-switcher-wrap .feed-scope-btn {
2837 display: inline-flex;
2838 align-items: center;
2839 padding: .32rem .95rem;
2840 min-height: 30px;
2841 border: none !important;
2842 border-radius: 999px !important;
2843 background: transparent !important;
2844 color: var(--ink-muted) !important;
2845 font-family: var(--font-ui);
2846 font-size: .82rem;
2847 font-weight: 500 !important;
2848 text-decoration: none !important;
2849 cursor: pointer;
2850 transition: all .15s;
2851}
2852.view-switcher-wrap .feed-scope-btn:hover { color: var(--ink) !important; }
2853.view-switcher-wrap .feed-scope-btn.is-active {
2854 background: var(--ink) !important;
2855 color: var(--paper) !important;
2856}
2857
2858.grid-cols-picker {
2859 display: none; /* default hidden — desktop + grid-active maakt 'm zichtbaar */
2860 gap: 2px;
2861 padding: 0;
2862}
2863.grid-cols-btn {
2864 display: inline-flex;
2865 align-items: center;
2866 justify-content: center;
2867 min-width: 36px;
2868 height: 32px;
2869 padding: 0 .6rem;
2870 background: transparent;
2871 border: 1px solid var(--rule);
2872 color: var(--ink-muted);
2873 font-family: var(--font-ui);
2874 font-size: .85rem;
2875 font-weight: 500;
2876 cursor: pointer;
2877 transition: all .12s;
2878}
2879.grid-cols-btn:first-child { border-radius: 999px 0 0 999px; }
2880.grid-cols-btn:last-child { border-radius: 0 999px 999px 0; }
2881.grid-cols-btn:not(:first-child):not(:last-child) { border-left: none; border-right: none; }
2882.grid-cols-btn:hover { color: var(--ink); }
2883/* Active state puur via body[data-grid-cols] — geen is-active-class meer. */
2884body[data-grid-cols="2"] .grid-cols-btn[data-cols="2"],
2885body[data-grid-cols="3"] .grid-cols-btn[data-cols="3"],
2886body[data-grid-cols="4"] .grid-cols-btn[data-cols="4"] {
2887 background: var(--ink);
2888 color: var(--paper);
2889 border-color: var(--ink);
2890}
2891
2892/* Desktop + grid-view → toon cols-picker (op de home-feed; niet op archief) */
2893@media (min-width: 600px) {
2894 body.on-home[data-feed-view="grid"] .grid-cols-picker {
2895 display: inline-flex;
2896 }
2897}
2898
2899/* Kolom-overrides op desktop. Mobiel negeert dit (staat vast op 2). Geldt op ELKE
2900 feed met grid (home én cirkel/tag/type/user) — scope op .feed-grid .grid-tiles. */
2901@media (min-width: 600px) {
2902 body[data-grid-cols="2"] .feed-grid .grid-tiles { grid-template-columns: repeat(2, 1fr); }
2903 body[data-grid-cols="3"] .feed-grid .grid-tiles { grid-template-columns: repeat(3, 1fr); }
2904 body[data-grid-cols="4"] .feed-grid .grid-tiles { grid-template-columns: repeat(4, 1fr); }
2905}
2906
2907/* Gradient-tile: iets meer contrast voor light + dark mode zodat titel altijd leesbaar is */
2908.grid-tile-gradient {
2909 background-image: linear-gradient(135deg,
2910 hsl(var(--tile-hue, 30), 55%, 72%),
2911 hsl(calc(var(--tile-hue, 30) + 40), 45%, 60%));
2912}
2913[data-theme="dark"] .grid-tile-gradient {
2914 background-image: linear-gradient(135deg,
2915 hsl(var(--tile-hue, 30), 40%, 30%),
2916 hsl(calc(var(--tile-hue, 30) + 40), 30%, 18%));
2917}
2918.grid-tile-gradient .grid-tile-title {
2919 color: #fff;
2920 text-shadow: 0 1px 3px rgba(0,0,0,.25);
2921}
2922[data-theme="dark"] .grid-tile-gradient .grid-tile-title {
2923 color: #fff;
2924 text-shadow: 0 1px 2px rgba(0,0,0,.5);
2925}
2926
2927/* ============================================================
2928 v8.0.2 — COMPACT DESIGN OVERRIDES
2929 Tighter masthead, padding, margins overall. Profiel-header
2930 collapse/expand blijft zoals 'ie was.
2931 ============================================================ */
2932
2933/* Masthead: compacter */
2934.masthead { padding: calc(.55rem + var(--ios-safe-top, 0px)) 0 .55rem; }
2935.masthead-inner { gap: 1rem; }
2936.site-title { font-size: 1.25rem; }
2937.nav-link, .nav-btn { padding: .4rem .7rem; min-height: 2rem; font-size: .82rem; }
2938
2939/* Main content padding */
2940main { padding-top: 1rem; }
2941.page { padding-block: 1rem 1.75rem; }
2942
2943/* View switcher-bar strakker */
2944.view-switcher { padding: .4rem 0; gap: .3rem; }
2945.view-switch-btn { padding: .4rem .85rem; min-height: 38px; font-size: .8rem; }
2946.grid-cols-btn { min-width: 32px; height: 28px; padding: 0 .5rem; font-size: .8rem; }
2947
2948/* Post header spacing terug */
2949.post-header { margin: 0 0 1.25rem; }
2950.post-title { margin-bottom: .35rem; }
2951.post-meta { font-size: .78rem; }
2952.post-tags { margin-top: .6rem; gap: .3rem; }
2953.post-tag { font-size: .7rem; padding: .15rem .55rem; }
2954
2955/* Article footer + pagination compacter */
2956.article-footer { padding-top: 1.25rem; margin-top: 1.5rem; }
2957.pagination { padding-block: 1.25rem 2rem; margin-top: 1.5rem; }
2958.pagination-item { padding: .75rem .95rem; min-height: 4rem; }
2959.pagination-title { font-size: .95rem; }
2960
2961/* Site footer compacter */
2962.site-footer { padding: 1.25rem 0 calc(1.25rem + env(safe-area-inset-bottom, 0px)); margin-top: 2rem; font-size: .78rem; }
2963.site-footer-inner { gap: .75rem; }
2964
2965/* Profiel-header: full mode iets minder riant (compact mode blijft hetzelfde) */
2966.profile-header { padding: 1rem 0; }
2967.profile-photo { width: 72px; height: 72px; }
2968.profile-photo-fallback { font-size: 1.8rem; }
2969.profile-name { font-size: 1.2rem; }
2970.profile-bio { font-size: .85rem; margin-top: .15rem; }
2971.profile-links { margin-top: .5rem; gap: .4rem; }
2972.profile-links a,
2973.profile-links .profile-fedi-link { width: 32px; height: 32px; }
2974
2975@media (min-width: 768px) {
2976 .profile-header { padding: 1.35rem 0; }
2977 .profile-photo { width: 92px; height: 92px; }
2978 .profile-photo-fallback { font-size: 2.4rem; }
2979 .profile-name { font-size: 1.4rem; }
2980 .profile-bio { font-size: .95rem; }
2981 .profile-header-inner { gap: 1.1rem; }
2982 /* Compact-mode op desktop blijft klein zoals we hadden afgesproken */
2983 .on-post .profile-photo,
2984 .on-special .profile-photo { width: 42px; height: 42px; }
2985}
2986
2987/* Grid-tegels iets strakker gaten */
2988.grid-tiles { gap: 3px; }
2989
2990/* Post-cover margin */
2991.post-cover { margin: 0 0 1rem; }
2992
2993/* Audio player wat lichter */
2994#pcms-audio-bar { padding: .55rem 1rem; }
2995
2996/* v8.1 — pagination CTA + mobile tap target */
2997.pagination-cta {
2998 display: inline-block;
2999 font-family: var(--font-ui);
3000 font-size: .72rem;
3001 font-weight: 600;
3002 color: var(--accent);
3003 margin-top: .35rem;
3004 letter-spacing: .02em;
3005 opacity: .9;
3006}
3007a.pagination-item:hover .pagination-cta { opacity: 1; }
3008
3009/* Mobiel: nog meer tap-feedback + iets prominenter */
3010@media (max-width: 640px) {
3011 a.pagination-item {
3012 padding: 1.1rem 1rem;
3013 min-height: 5.5rem;
3014 border-width: 2px;
3015 }
3016 a.pagination-item:active {
3017 background: color-mix(in srgb, var(--accent) 10%, var(--paper-2));
3018 transform: scale(.98);
3019 }
3020 .pagination-title { font-size: 1rem; }
3021 .pagination-cta { font-size: .75rem; }
3022 .pagination .icon { width: 1.5em; height: 1.5em; }
3023}
3024
3025
3026
3027/* v8.3 / v9.4 — PWA install button (alleen zichtbaar als browser install ondersteunt) */
3028.nav-install-btn[hidden] { display: none; }
3029.nav-install-btn {
3030 position: relative;
3031 display: inline-flex;
3032 align-items: center;
3033 justify-content: center;
3034 gap: .35rem;
3035 background: linear-gradient(135deg,
3036 var(--accent),
3037 color-mix(in srgb, var(--accent) 80%, #000));
3038 color: #fff;
3039 border: none;
3040 border-radius: .65rem;
3041 padding: .45rem .85rem;
3042 font-size: .8rem;
3043 font-weight: 600;
3044 line-height: 1;
3045 cursor: pointer;
3046 overflow: hidden;
3047 isolation: isolate;
3048 box-shadow:
3049 0 1px 0 rgba(255,255,255,.15) inset,
3050 0 2px 6px color-mix(in srgb, var(--accent) 35%, transparent);
3051 transition:
3052 transform .15s cubic-bezier(.4, 0, .2, 1),
3053 box-shadow .2s ease,
3054 filter .15s ease;
3055}
3056.nav-install-btn::before {
3057 content: "";
3058 position: absolute;
3059 top: 0;
3060 left: -100%;
3061 width: 60%;
3062 height: 100%;
3063 background: linear-gradient(110deg,
3064 transparent 30%,
3065 rgba(255,255,255,.22) 50%,
3066 transparent 70%);
3067 z-index: -1;
3068 animation: pcmsInstallShimmer 4s ease-in-out infinite;
3069 pointer-events: none;
3070}
3071.nav-install-btn:hover {
3072 transform: translateY(-1px);
3073 filter: brightness(1.08);
3074 box-shadow:
3075 0 1px 0 rgba(255,255,255,.2) inset,
3076 0 4px 10px color-mix(in srgb, var(--accent) 50%, transparent);
3077}
3078.nav-install-btn:active { transform: translateY(0); }
3079.nav-install-btn .icon {
3080 flex-shrink: 0;
3081 transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
3082}
3083.nav-install-btn:hover .icon { transform: translateY(-1px); }
3084@media (prefers-reduced-motion: reduce) {
3085 .nav-install-btn::before { animation: none; left: -100%; }
3086 .nav-install-btn:hover { transform: none; }
3087 .nav-install-btn:hover .icon { transform: none; }
3088}
3089/* Als PWA al draait (standalone mode) — verberg install-prompt knop volledig */
3090@media all and (display-mode: standalone) {
3091 #pwa-install-btn { display: none !important; }
3092}
3093
3094/* ========== v8.9.9 — Privé-post indicators ========== */
3095.post-private-banner {
3096 display: flex;
3097 align-items: center;
3098 gap: .6rem;
3099 padding: .75rem 1rem;
3100 background: color-mix(in srgb, #eab308 12%, var(--paper, #fff));
3101 border: 1px solid color-mix(in srgb, #eab308 40%, transparent);
3102 border-radius: 8px;
3103 margin: 0 0 1rem;
3104 font-size: .88rem;
3105 color: var(--ink, #1a1a1a);
3106}
3107.post-private-banner strong {
3108 color: #b45309;
3109}
3110
3111.grid-tile-private {
3112 position: absolute;
3113 top: 8px;
3114 left: 8px;
3115 padding: 3px 8px;
3116 background: rgba(0,0,0,0.7);
3117 color: #fde68a;
3118 font-size: .7rem;
3119 font-weight: 700;
3120 border-radius: 999px;
3121 z-index: 3;
3122 backdrop-filter: blur(4px);
3123 -webkit-backdrop-filter: blur(4px);
3124}
3125
3126/* ========== v8.9.10 — Social chip (inline in post-body) ========== */
3127.social-chip {
3128 display: inline-flex;
3129 align-items: center;
3130 gap: .45rem;
3131 padding: .35rem .75rem;
3132 background: color-mix(in srgb, var(--accent) 10%, transparent);
3133 border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
3134 border-radius: 999px;
3135 color: var(--ink, #1a1a1a);
3136 text-decoration: none;
3137 font-family: var(--font-ui, system-ui);
3138 font-size: .85rem;
3139 font-weight: 600;
3140 line-height: 1.2;
3141 transition: all .15s;
3142 vertical-align: middle;
3143 margin: 0 .1rem;
3144}
3145.social-chip:hover {
3146 background: var(--accent);
3147 color: #fff;
3148 border-color: var(--accent);
3149 text-decoration: none;
3150 transform: translateY(-1px);
3151 box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 40%, transparent);
3152}
3153.social-chip .icon {
3154 width: 16px;
3155 height: 16px;
3156 flex-shrink: 0;
3157}
3158.social-chip-icon-only {
3159 width: 36px;
3160 height: 36px;
3161 padding: 0;
3162 justify-content: center;
3163 border-radius: 50%;
3164}
3165.social-chip-icon-only .icon {
3166 width: 18px;
3167 height: 18px;
3168}
3169
3170/* v8.9.34 — player hidden state + post audio blocks
3171 v9.3 — Hide-rules uitgeschakeld: mini-player blijft permanent zichtbaar
3172 zodat 'ie niet meer verdwijnt bij browser-back of navigatie. */
3173.audio-player.is-hidden {
3174 /* display: none !important; */
3175}
3176body:not(.has-audio-player) #pcms-audio-player.is-hidden {
3177 /* display: none !important; */
3178}
3179
3180/* Post audio track — single track row in een post */
3181/* Lokale audio-track — visueel consistent met .post-audio-external */
3182.post-audio-track {
3183 display: flex;
3184 align-items: center;
3185 gap: .75rem;
3186 padding: .65rem .85rem;
3187 background: var(--paper-2, color-mix(in srgb, var(--ink) 4%, transparent));
3188 border: 1px solid var(--rule, rgba(0,0,0,.08));
3189 border-radius: 10px;
3190 margin: .75rem 0;
3191 transition: background .15s, border-color .15s;
3192}
3193.post-audio-track:hover {
3194 border-color: var(--accent, #c2410c);
3195 background: color-mix(in srgb, var(--accent, #c2410c) 5%, var(--paper-2, transparent));
3196}
3197/* Korte highlight wanneer je via de mini-speler naar deze track springt. */
3198.post-audio-track.pat-flash,
3199.post-album-track-compact.pat-flash {
3200 animation: patFlash 1.6s ease-out;
3201 border-radius: 8px;
3202}
3203/* Blijvende highlight op de track die NU actief is in de speler. */
3204.post-audio-track.pat-playing,
3205.post-album-track-compact.pat-playing {
3206 background: color-mix(in srgb, var(--accent, #c2410c) 12%, var(--paper-2, transparent));
3207 box-shadow: inset 3px 0 0 0 var(--accent, #c2410c);
3208 border-radius: 8px;
3209}
3210@keyframes patFlash {
3211 0%, 30% { border-color: var(--accent, #c2410c); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #c2410c) 35%, transparent); }
3212 100% { box-shadow: 0 0 0 0 transparent; }
3213}
3214.post-audio-track .pat-play {
3215 flex-shrink: 0;
3216 width: 42px;
3217 height: 42px;
3218 border-radius: 8px; /* zelfde rounded-square als pae-icon */
3219 border: none;
3220 background: var(--accent, #c2410c);
3221 color: var(--paper, #fff);
3222 cursor: pointer;
3223 display: inline-flex;
3224 align-items: center;
3225 justify-content: center;
3226 transition: transform .1s, background .15s;
3227 padding: 0;
3228 position: relative;
3229 overflow: hidden;
3230}
3231.post-audio-track .pat-play:hover { transform: scale(1.04); }
3232.post-audio-track .pat-play:active { transform: scale(.96); }
3233.post-audio-track .pat-play svg,
3234.post-audio-track .pat-play .pat-sitelogo {
3235 width: 100%; height: 100%;
3236 position: absolute;
3237 top: 0; left: 0;
3238 transition: opacity .15s;
3239}
3240.post-audio-track .pat-play .icon-play,
3241.post-audio-track .pat-play .icon-pause {
3242 width: 18px; height: 18px;
3243 position: absolute;
3244 top: 50%; left: 50%;
3245 transform: translate(-50%, -50%);
3246 fill: currentColor;
3247 opacity: 0; /* verborgen tot hover of is-current */
3248}
3249/* Site logo: object-cover binnen 42x42 box */
3250.post-audio-track .pat-play .pat-sitelogo {
3251 object-fit: cover;
3252 opacity: 1;
3253}
3254.post-audio-track .pat-play .pat-sitelogo-fallback {
3255 padding: 11px; /* SVG music-note iets kleiner in box */
3256 opacity: 1;
3257}
3258/* Bij hover: site logo faded, play-icoon verschijnt */
3259.post-audio-track:hover .pat-play .pat-sitelogo { opacity: 0.25; }
3260.post-audio-track:hover .pat-play .icon-play { opacity: 1; }
3261/* Bij current + playing: toon pause-icon */
3262.post-audio-track.is-current .pat-play .pat-sitelogo { opacity: 0.25; }
3263.post-audio-track.is-current .pat-play .icon-play { opacity: 1; }
3264.post-audio-track.is-current.is-playing .pat-play .icon-play { opacity: 0; }
3265.post-audio-track.is-current.is-playing .pat-play .icon-pause { opacity: 1; }
3266.post-audio-track.is-current {
3267 border-color: var(--accent, #c2410c);
3268 background: color-mix(in srgb, var(--accent, #c2410c) 10%, transparent);
3269}
3270.post-audio-track .pat-meta {
3271 flex: 1;
3272 min-width: 0;
3273 display: flex;
3274 flex-direction: column;
3275 gap: 2px;
3276}
3277.post-audio-track .pat-title {
3278 display: block;
3279 font-weight: 600;
3280 color: var(--ink);
3281 font-size: .95rem;
3282 overflow: hidden;
3283 text-overflow: ellipsis;
3284 white-space: nowrap;
3285}
3286.post-audio-track .pat-artist {
3287 display: block;
3288 font-size: .78rem;
3289 color: var(--ink-muted, var(--ink));
3290 opacity: .65;
3291 overflow: hidden;
3292 text-overflow: ellipsis;
3293 white-space: nowrap;
3294}
3295.post-audio-track .pat-duration {
3296 flex-shrink: 0;
3297 font-family: ui-monospace, monospace;
3298 font-size: .8rem;
3299 opacity: .55;
3300}
3301
3302/* Album block in een post */
3303.post-album {
3304 position: relative;
3305 border: 1px solid var(--rule, rgba(0,0,0,.1));
3306 border-radius: 14px;
3307 overflow: hidden;
3308 margin: 1.25rem 0;
3309 background: var(--paper-2, color-mix(in srgb, var(--ink) 3%, transparent));
3310}
3311.post-album-header {
3312 display: flex;
3313 gap: .75rem;
3314 padding: .55rem .7rem;
3315 align-items: center;
3316}
3317.post-album-cover {
3318 width: 120px;
3319 height: 120px;
3320 border-radius: 8px;
3321 background-size: cover;
3322 background-position: center;
3323 background-color: var(--rule);
3324 flex-shrink: 0;
3325}
3326/* v9.0 — Collage van track-covers als album-cover leeg is */
3327.post-album-cover-collage {
3328 display: grid;
3329 grid-template-columns: 1fr 1fr;
3330 grid-template-rows: 1fr 1fr;
3331 gap: 0;
3332 overflow: hidden;
3333 background: transparent;
3334}
3335.post-album-cover-collage .post-album-cover-tile {
3336 background-size: cover;
3337 background-position: center;
3338 width: 100%;
3339 height: 100%;
3340}
3341/* Empty state: gradient met muziek-noot */
3342.post-album-cover-empty {
3343 display: flex;
3344 align-items: center;
3345 justify-content: center;
3346 background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 25%, var(--paper-2)), color-mix(in srgb, var(--accent) 10%, var(--paper)));
3347 color: var(--accent, #c2410c);
3348}
3349.post-album-cover-empty svg {
3350 width: 42%;
3351 height: 42%;
3352 opacity: .55;
3353}
3354.post-album-info {
3355 flex: 1;
3356 min-width: 0;
3357}
3358.post-album-label {
3359 text-transform: uppercase;
3360 font-size: .68rem;
3361 letter-spacing: .1em;
3362 opacity: .55;
3363 margin: 0 0 .15rem;
3364 font-weight: 700;
3365}
3366.post-album-title {
3367 font-family: var(--font-display);
3368 font-size: 1.1rem;
3369 font-weight: 600;
3370 margin: 0 0 .1rem;
3371 line-height: 1.15;
3372 letter-spacing: -0.01em;
3373}
3374.post-album-artist {
3375 font-size: .88rem;
3376 opacity: .8;
3377 margin: 0 0 .12rem;
3378 line-height: 1.25;
3379}
3380.post-album-meta {
3381 font-size: .74rem;
3382 opacity: .55;
3383 margin: 0;
3384 line-height: 1.2;
3385}
3386.post-album-playall {
3387 margin-top: .75rem;
3388 padding: .45rem .9rem;
3389 background: var(--accent, #c2410c);
3390 color: var(--paper, #fff);
3391 border: none;
3392 border-radius: 6px;
3393 font-weight: 600;
3394 cursor: pointer;
3395 font-size: .88rem;
3396 display: inline-flex;
3397 align-items: center;
3398 gap: .35rem;
3399}
3400.post-album-playall:hover { filter: brightness(1.08); }
3401
3402/* ============================================================
3403 v9.0 — Album cover clickable button
3404 ============================================================ */
3405.post-album-cover-btn {
3406 position: relative;
3407 background: none;
3408 border: none;
3409 padding: 0;
3410 margin: 0;
3411 cursor: pointer;
3412 flex-shrink: 0;
3413 border-radius: 8px;
3414 overflow: hidden;
3415 display: block;
3416 width: auto;
3417 /* v9.1 — voorkom mobile 300ms double-tap zoom delay, anders zou 2× snel klikken
3418 een zoom triggeren i.p.v. 2× click-events */
3419 touch-action: manipulation;
3420 -webkit-tap-highlight-color: transparent;
3421}
3422.post-album-cover-btn .post-album-cover {
3423 display: block;
3424 width: 76px;
3425 height: 76px;
3426 border-radius: 7px;
3427 background-size: cover;
3428 background-position: center;
3429 background-color: var(--rule);
3430 transition: transform .25s ease;
3431}
3432.post-album-cover-btn:hover .post-album-cover {
3433 transform: scale(1.04);
3434}
3435.post-album-cover-btn .post-album-cover-empty {
3436 background: linear-gradient(135deg,
3437 color-mix(in srgb, var(--accent, #c2410c) 35%, var(--paper)),
3438 color-mix(in srgb, var(--accent, #c2410c) 10%, var(--paper-2)));
3439 display: flex;
3440 align-items: center;
3441 justify-content: center;
3442}
3443.post-album-cover-btn .post-album-cover-empty svg {
3444 width: 28px;
3445 height: 28px;
3446 color: color-mix(in srgb, var(--accent, #c2410c) 60%, transparent);
3447}
3448/* Play overlay op hover */
3449.post-album-cover-play {
3450 position: absolute;
3451 inset: 0;
3452 display: flex;
3453 align-items: center;
3454 justify-content: center;
3455 background: rgba(0, 0, 0, .35);
3456 opacity: 0;
3457 transition: opacity .2s ease;
3458 border-radius: 8px;
3459 pointer-events: none;
3460}
3461.post-album-cover-play svg {
3462 width: 48px;
3463 height: 48px;
3464 color: #fff;
3465 filter: drop-shadow(0 2px 8px rgba(0,0,0,.4));
3466}
3467.post-album-cover-btn:hover .post-album-cover-play,
3468.post-album-cover-btn:focus-visible .post-album-cover-play {
3469 opacity: 1;
3470}
3471
3472/* ============================================================
3473 v1 P52 — Admin actions overlay (edit / delete)
3474 Only rendered when the viewer has god role. Sits top-right
3475 of the card so it doesn't compete with the cover play affordance.
3476 ============================================================ */
3477.post-album-actions {
3478 position: absolute;
3479 top: .4rem;
3480 right: .4rem;
3481 display: flex;
3482 gap: .25rem;
3483 z-index: 2;
3484}
3485.post-album-action {
3486 width: 28px;
3487 height: 28px;
3488 border-radius: 6px;
3489 border: 1px solid var(--rule);
3490 background: color-mix(in srgb, var(--paper) 78%, transparent);
3491 backdrop-filter: blur(8px);
3492 -webkit-backdrop-filter: blur(8px);
3493 color: var(--ink);
3494 display: inline-flex;
3495 align-items: center;
3496 justify-content: center;
3497 cursor: pointer;
3498 text-decoration: none;
3499 opacity: .65;
3500 padding: 0;
3501 transition: opacity .15s ease, transform .15s ease, background .15s ease, color .15s ease, border-color .15s ease;
3502 -webkit-tap-highlight-color: transparent;
3503}
3504.post-album-action:hover,
3505.post-album-action:focus-visible {
3506 opacity: 1;
3507 transform: translateY(-1px);
3508 outline: none;
3509}
3510.post-album-action.is-danger:hover,
3511.post-album-action.is-danger:focus-visible {
3512 background: color-mix(in srgb, #c2410c 18%, var(--paper));
3513 border-color: color-mix(in srgb, #c2410c 45%, var(--rule));
3514 color: #c2410c;
3515}
3516.post-album-action svg {
3517 width: 15px;
3518 height: 15px;
3519 display: block;
3520}
3521
3522/* ============================================================
3523 v9.0 — Compacte tracklist (informatief, niet-klikbaar)
3524 ============================================================ */
3525.post-album-tracks {
3526 list-style: none;
3527 padding: 0;
3528 margin: 0;
3529 border-top: 1px solid var(--rule);
3530}
3531/* v9.4 — Playlist insert modal rows */
3532.pli-row {
3533 display: flex;
3534 align-items: center;
3535 gap: .75rem;
3536 padding: .65rem .5rem;
3537 border-bottom: 1px solid var(--border);
3538}
3539.pli-row:last-child { border-bottom: none; }
3540.pli-row-cover {
3541 width: 44px;
3542 height: 44px;
3543 border-radius: 6px;
3544 background-size: cover;
3545 background-position: center;
3546 background-color: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3547 flex-shrink: 0;
3548 display: flex;
3549 align-items: center;
3550 justify-content: center;
3551 font-size: 1.4rem;
3552}
3553.pli-row-info {
3554 flex: 1;
3555 min-width: 0;
3556}
3557.pli-row-title {
3558 font-weight: 600;
3559 overflow: hidden;
3560 text-overflow: ellipsis;
3561 white-space: nowrap;
3562}
3563.pli-row-meta {
3564 font-size: .82rem;
3565 overflow: hidden;
3566 text-overflow: ellipsis;
3567 white-space: nowrap;
3568}
3569.post-playlist-placeholder {
3570 margin: 1rem 0;
3571 user-select: none;
3572}
3573
3574/* v9.4 — Generic modal classes (gebruikt door playlist-editor en andere modals) */
3575.pcms-modal-backdrop {
3576 position: fixed;
3577 inset: 0;
3578 background: rgba(0, 0, 0, .6);
3579 display: flex;
3580 align-items: center;
3581 justify-content: center;
3582 z-index: 9000;
3583 padding: 1rem;
3584 box-sizing: border-box;
3585 overflow-y: auto;
3586}
3587.pcms-modal {
3588 background: var(--paper, #fff);
3589 color: var(--ink, #000);
3590 border-radius: 12px;
3591 width: 100%;
3592 max-width: 640px;
3593 max-height: calc(100vh - 2rem);
3594 display: flex;
3595 flex-direction: column;
3596 overflow: hidden;
3597 box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
3598}
3599.pcms-modal-header {
3600 display: flex;
3601 align-items: center;
3602 justify-content: space-between;
3603 padding: 1rem 1.25rem;
3604 border-bottom: 1px solid var(--border);
3605 flex-shrink: 0;
3606}
3607.pcms-modal-header h3 { font-size: 1.1rem; }
3608.pcms-modal-close {
3609 background: transparent;
3610 border: none;
3611 font-size: 1.6rem;
3612 line-height: 1;
3613 cursor: pointer;
3614 padding: .25rem .5rem;
3615 color: var(--fg-muted, #666);
3616 border-radius: 4px;
3617}
3618.pcms-modal-close:hover {
3619 background: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3620}
3621.pcms-modal-body {
3622 padding: 1.25rem;
3623 overflow-y: auto;
3624 overscroll-behavior: contain;
3625 flex: 1;
3626 min-height: 0;
3627}
3628.pcms-modal-footer {
3629 display: flex;
3630 gap: .5rem;
3631 justify-content: flex-end;
3632 padding: .75rem 1.25rem;
3633 border-top: 1px solid var(--border);
3634 flex-shrink: 0;
3635 background: color-mix(in srgb, var(--ink, #000) 3%, transparent);
3636}
3637
3638/* On mobile: full-screen modal */
3639@media (max-width: 600px) {
3640 .pcms-modal-backdrop {
3641 padding: 0;
3642 }
3643 .pcms-modal {
3644 border-radius: 0;
3645 max-width: 100%;
3646 max-height: 100vh;
3647 height: 100vh;
3648 }
3649}
3650
3651/* v9.4 — Media → Playlists tab */
3652.playlists-page-header {
3653 display: flex;
3654 flex-wrap: wrap;
3655 gap: 1rem;
3656 align-items: center;
3657 justify-content: space-between;
3658 margin-bottom: 1.25rem;
3659}
3660.playlists-page-header > p { flex: 1; min-width: 200px; }
3661.playlists-grid {
3662 display: grid;
3663 grid-template-columns: 1fr;
3664 gap: .75rem;
3665}
3666@media (min-width: 720px) {
3667 .playlists-grid { grid-template-columns: repeat(2, 1fr); }
3668}
3669@media (min-width: 1100px) {
3670 .playlists-grid { grid-template-columns: repeat(3, 1fr); }
3671}
3672.playlist-card {
3673 display: grid;
3674 grid-template-columns: 64px 1fr auto;
3675 gap: .75rem;
3676 align-items: center;
3677 padding: .75rem;
3678 border: 1px solid var(--border);
3679 border-radius: var(--radius);
3680 background: var(--paper, #fff);
3681}
3682.playlist-card-cover {
3683 width: 64px;
3684 height: 64px;
3685 border-radius: 8px;
3686 overflow: hidden;
3687 background-color: color-mix(in srgb, var(--ink, #000) 6%, transparent);
3688 display: flex;
3689 align-items: center;
3690 justify-content: center;
3691}
3692.playlist-card-cover img {
3693 width: 100%;
3694 height: 100%;
3695 object-fit: cover;
3696}
3697.playlist-card-cover-empty { font-size: 1.6rem; opacity: .5; }
3698.playlist-card-info { min-width: 0; }
3699.playlist-card-title {
3700 font-weight: 600;
3701 overflow: hidden;
3702 text-overflow: ellipsis;
3703 white-space: nowrap;
3704}
3705.playlist-card-artist,
3706.playlist-card-meta {
3707 font-size: .82rem;
3708 overflow: hidden;
3709 text-overflow: ellipsis;
3710 white-space: nowrap;
3711}
3712.playlist-card-actions {
3713 display: flex;
3714 gap: .25rem;
3715 flex-shrink: 0;
3716}
3717
3718/* v9.4 — Playlist editor modal (mobile-friendly, single-column) */
3719.pl-editor {
3720 /* Erft van .pcms-modal */
3721}
3722.pl-editor-meta {
3723 display: grid;
3724 grid-template-columns: 1fr;
3725 gap: .75rem;
3726 margin-bottom: 1rem;
3727}
3728@media (min-width: 560px) {
3729 .pl-editor-meta {
3730 grid-template-columns: 1fr 1fr;
3731 }
3732 .pl-editor-meta .pl-editor-field-full { grid-column: 1 / -1; }
3733}
3734.pl-editor-field {
3735 display: flex;
3736 flex-direction: column;
3737 gap: .25rem;
3738 min-width: 0;
3739}
3740.pl-editor-field span {
3741 font-size: .82rem;
3742 color: var(--fg-muted, #666);
3743 font-weight: 500;
3744}
3745.pl-editor-field input,
3746.pl-editor-field select {
3747 width: 100%;
3748 box-sizing: border-box;
3749 padding: .5rem .65rem;
3750 font-size: .95rem;
3751 border: 1px solid var(--border);
3752 border-radius: 6px;
3753 background: var(--paper, #fff);
3754 color: var(--ink, #000);
3755}
3756.pl-editor-field input:focus,
3757.pl-editor-field select:focus {
3758 outline: 2px solid var(--accent, #5a8a5a);
3759 outline-offset: -1px;
3760}
3761.pl-editor-section-title {
3762 margin: 1.25rem 0 .5rem;
3763 font-size: 1rem;
3764 font-weight: 600;
3765}
3766.pl-tracks-selected {
3767 border: 1px solid var(--border);
3768 border-radius: var(--radius);
3769 background: var(--paper, #fff);
3770 min-height: 60px;
3771 margin-bottom: 1rem;
3772 padding: .25rem;
3773}
3774.pl-tracks-empty {
3775 padding: 1.5rem;
3776 text-align: center;
3777 color: var(--fg-muted, #666);
3778 font-size: .9rem;
3779}
3780.pl-track-row {
3781 display: grid;
3782 grid-template-columns: 32px 36px 1fr auto;
3783 gap: .5rem;
3784 align-items: center;
3785 padding: .5rem;
3786 border-bottom: 1px solid var(--border);
3787 background: var(--paper, #fff);
3788 user-select: none;
3789 touch-action: pan-x;
3790}
3791.pl-track-row:last-child { border-bottom: none; }
3792.pl-track-row.is-dragging {
3793 opacity: .55;
3794 transform: scale(.98);
3795 background: color-mix(in srgb, var(--accent, #5a8a5a) 10%, transparent);
3796 border-radius: 6px;
3797}
3798.pl-track-row.drop-target-above {
3799 box-shadow: inset 0 2px 0 0 var(--accent, #5a8a5a);
3800}
3801.pl-track-row.drop-target-below {
3802 box-shadow: inset 0 -2px 0 0 var(--accent, #5a8a5a);
3803}
3804.pl-track-handle {
3805 cursor: grab;
3806 font-size: 1.2rem;
3807 line-height: 1;
3808 color: var(--fg-muted, #666);
3809 display: flex;
3810 align-items: center;
3811 justify-content: center;
3812 height: 32px;
3813 width: 32px;
3814 border-radius: 4px;
3815 flex-shrink: 0;
3816}
3817.pl-track-handle:active { cursor: grabbing; }
3818.pl-track-handle:hover {
3819 background: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3820}
3821.pl-track-num {
3822 text-align: center;
3823 color: var(--fg-muted, #666);
3824 font-size: .85rem;
3825 width: 36px;
3826}
3827.pl-track-info {
3828 min-width: 0;
3829 overflow: hidden;
3830}
3831.pl-track-title {
3832 font-weight: 500;
3833 overflow: hidden;
3834 text-overflow: ellipsis;
3835 white-space: nowrap;
3836}
3837.pl-track-artist {
3838 font-size: .78rem;
3839 color: var(--fg-muted, #666);
3840 overflow: hidden;
3841 text-overflow: ellipsis;
3842 white-space: nowrap;
3843}
3844.pl-track-remove {
3845 background: transparent;
3846 border: none;
3847 cursor: pointer;
3848 padding: .35rem;
3849 border-radius: 4px;
3850 color: var(--fg-muted, #666);
3851 font-size: 1.2rem;
3852 line-height: 1;
3853}
3854.pl-track-remove:hover {
3855 background: color-mix(in srgb, #c00 12%, transparent);
3856 color: #c00;
3857}
3858
3859/* Available tracks panel */
3860.pl-tracks-available-panel {
3861 border: 1px solid var(--border);
3862 border-radius: var(--radius);
3863 background: var(--paper, #fff);
3864}
3865.pl-tracks-available-search {
3866 padding: .5rem;
3867 border-bottom: 1px solid var(--border);
3868}
3869.pl-tracks-available-search input {
3870 width: 100%;
3871 box-sizing: border-box;
3872}
3873.pl-tracks-available-list {
3874 max-height: 30vh;
3875 overflow-y: auto;
3876}
3877.pl-track-row-available {
3878 display: grid;
3879 grid-template-columns: 1fr auto;
3880 gap: .5rem;
3881 align-items: center;
3882 padding: .5rem;
3883 border-bottom: 1px solid var(--border);
3884 cursor: pointer;
3885}
3886.pl-track-row-available:last-child { border-bottom: none; }
3887.pl-track-row-available:hover {
3888 background: color-mix(in srgb, var(--accent, #5a8a5a) 8%, transparent);
3889}
3890.pl-track-row-available.is-already-added {
3891 opacity: .4;
3892 pointer-events: none;
3893}
3894.pl-track-add-btn {
3895 background: transparent;
3896 border: 1px solid var(--border);
3897 border-radius: 4px;
3898 padding: .25rem .5rem;
3899 cursor: pointer;
3900 font-size: .85rem;
3901 color: var(--accent, #5a8a5a);
3902}
3903
3904/* v9.3 — Tracklist items zijn nu klikbare <button class="pat-row"> binnen <li>.
3905 De LI is puur een container zonder visuele styling; alles gebeurt op de button. */
3906.post-album-track-compact {
3907 padding: 0;
3908 margin: 0;
3909 border-bottom: 1px solid var(--rule);
3910 list-style: none;
3911}
3912.post-album-track-compact:last-child { border-bottom: none; }
3913
3914.pat-row {
3915 display: grid;
3916 grid-template-columns: 32px 1fr auto;
3917 gap: .65rem;
3918 align-items: center;
3919 width: 100%;
3920 padding: .5rem .85rem;
3921 background: transparent;
3922 border: none;
3923 color: inherit;
3924 font: inherit;
3925 font-size: .82rem;
3926 text-align: left;
3927 cursor: pointer;
3928 position: relative;
3929 transition: background .15s ease;
3930}
3931.pat-row:hover {
3932 background: color-mix(in srgb, var(--ink, #000) 6%, transparent);
3933}
3934.pat-row:active { transform: scale(.995); }
3935[data-theme="dark"] .pat-row:hover {
3936 background: color-mix(in srgb, var(--paper, #fff) 10%, transparent);
3937}
3938
3939/* Leader: track-nummer OF cover-thumb (afhankelijk van kind).
3940 v9.3 — pat-leader is altijd 32×32, met overgang voor spinner-vervanging. */
3941.pat-row .pat-num,
3942.pat-row .pat-cover {
3943 width: 32px;
3944 height: 32px;
3945 border-radius: 4px;
3946 flex-shrink: 0;
3947 transition: opacity .25s ease, transform .25s ease;
3948}
3949.pat-row .pat-num {
3950 font-family: ui-monospace, monospace;
3951 font-size: .8rem;
3952 opacity: .5;
3953 display: flex;
3954 align-items: center;
3955 justify-content: center;
3956}
3957.pat-row .pat-cover {
3958 background-size: cover;
3959 background-position: center;
3960 background-color: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3961}
3962
3963/* v9.3 — Loading-spiraal als overlay op de leader-kolom.
3964 pat-num/pat-cover faden uit, spinner faded in via ::before. */
3965.pat-row::before {
3966 content: "";
3967 position: absolute;
3968 left: .85rem; top: 50%;
3969 width: 32px; height: 32px;
3970 transform: translateY(-50%);
3971 color: var(--accent, #c2410c);
3972 background-color: currentColor;
3973 -webkit-mask: url('/assets/spinner.svg') center/26px 26px no-repeat;
3974 mask: url('/assets/spinner.svg') center/26px 26px no-repeat;
3975 opacity: 0;
3976 transition: opacity .25s ease;
3977 pointer-events: none;
3978 animation: pat-spinner-rotate 1.2s linear infinite;
3979 animation-play-state: paused;
3980}
3981.pat-row.is-loading::before {
3982 opacity: 1;
3983 animation-play-state: running;
3984}
3985.pat-row.is-loading .pat-num,
3986.pat-row.is-loading .pat-cover {
3987 opacity: 0;
3988 transform: scale(.85);
3989}
3990@keyframes pat-spinner-rotate {
3991 from { transform: translateY(-50%) rotate(0deg); }
3992 to { transform: translateY(-50%) rotate(-360deg); }
3993}
3994
3995/* Meta-kolom */
3996.pat-row .pat-meta {
3997 display: flex;
3998 flex-direction: column;
3999 min-width: 0;
4000 gap: 1px;
4001 overflow: hidden;
4002}
4003.pat-row .pat-title {
4004 font-weight: 500;
4005 overflow: hidden;
4006 text-overflow: ellipsis;
4007 white-space: nowrap;
4008}
4009.pat-row .pat-artist {
4010 font-size: .72rem;
4011 opacity: .6;
4012 overflow: hidden;
4013 text-overflow: ellipsis;
4014 white-space: nowrap;
4015}
4016.pat-row .pat-duration {
4017 font-family: ui-monospace, monospace;
4018 font-size: .72rem;
4019 opacity: .55;
4020 font-variant-numeric: tabular-nums;
4021 white-space: nowrap;
4022}
4023.pat-row .pat-duration-empty {
4024 opacity: .25;
4025}
4026
4027/* is-current — actieve track in de player */
4028.pat-row.is-current {
4029 background: color-mix(in srgb, var(--accent, #c2410c) 12%, transparent);
4030}
4031.pat-row.is-current .pat-title,
4032.pat-row.is-current .pat-artist { color: var(--accent, #c2410c); }
4033
4034/* v9.3 — Marquee bij actief afspelen: titel scrollt heen-en-weer.
4035 --pat-shift wordt door JS gezet (= overflow in pixels). Bij 0 → geen
4036 beweging want translateX(0) blijft 0.
4037 Snelle cyclus (6s) met korte rust aan beide uiteinden (8%) zodat 't
4038 vlot voelt zonder onleesbaar te zijn. */
4039.pat-row.is-current.is-playing .pat-title {
4040 animation: pat-title-marquee 6s ease-in-out infinite alternate;
4041 text-overflow: clip;
4042 overflow: visible;
4043 will-change: transform;
4044}
4045@keyframes pat-title-marquee {
4046 0%, 8% { transform: translateX(0); }
4047 92%, 100% { transform: translateX(calc(-1 * var(--pat-shift, 0px))); }
4048}
4049
4050/* ============================================================
4051 v9.0 — CSS-migratie voor OUDE opgeslagen albums
4052 Oude posts hebben <li class="post-audio-track"> met play-knoppen + cover-spans.
4053 We renderen die VISUEEL als compact, zonder de HTML aan te passen.
4054 ============================================================ */
4055.post-album-tracks .post-audio-track {
4056 display: grid;
4057 grid-template-columns: 28px 1fr auto;
4058 gap: .75rem;
4059 align-items: center;
4060 padding: .5rem .85rem;
4061 margin: 0;
4062 border: none;
4063 border-bottom: 1px solid var(--rule);
4064 background: transparent;
4065 border-radius: 0;
4066 cursor: default;
4067 font-size: .92rem;
4068}
4069.post-album-tracks .post-audio-track:last-child { border-bottom: none; }
4070/* Verberg de cover-thumb en play-button in OUDE saved posts */
4071.post-album-tracks .post-audio-track .pat-cover,
4072.post-album-tracks .post-audio-track .pat-play {
4073 display: none !important;
4074}
4075.post-album-tracks .post-audio-track .pat-num {
4076 font-family: ui-monospace, monospace;
4077 font-size: .8rem;
4078 opacity: .45;
4079 text-align: center;
4080 width: auto;
4081}
4082.post-album-tracks .post-audio-track .pat-meta {
4083 display: flex;
4084 flex-direction: column;
4085 min-width: 0;
4086 gap: 1px;
4087}
4088.post-album-tracks .post-audio-track .pat-title {
4089 font-weight: 500;
4090 overflow: hidden;
4091 text-overflow: ellipsis;
4092 white-space: nowrap;
4093}
4094.post-album-tracks .post-audio-track .pat-artist {
4095 font-size: .78rem;
4096 opacity: .6;
4097}
4098.post-album-tracks .post-audio-track .pat-duration {
4099 font-family: ui-monospace, monospace;
4100 font-size: .78rem;
4101 opacity: .55;
4102}
4103.post-album-tracks .post-audio-track.is-current {
4104 background: color-mix(in srgb, var(--accent, #c2410c) 10%, transparent);
4105}
4106.post-album-tracks .post-audio-track.is-current .pat-num,
4107.post-album-tracks .post-audio-track.is-current .pat-title {
4108 color: var(--accent);
4109}
4110
4111@media (max-width: 540px) {
4112 .post-album-header { flex-direction: column; }
4113 .post-album-cover-btn .post-album-cover { width: 100%; max-width: 240px; height: auto; aspect-ratio: 1/1; }
4114}
4115@media (max-width: 380px) {
4116 .post-album-header { padding: .75rem; gap: .75rem; }
4117 .post-album-cover-btn .post-album-cover { max-width: 180px; }
4118 .post-album-title { font-size: 1.15rem; }
4119 .post-album-meta { font-size: .8rem; }
4120 .post-album-track-compact,
4121 .post-album-tracks .post-audio-track {
4122 grid-template-columns: 24px 1fr auto;
4123 gap: .5rem;
4124 padding: .4rem .6rem;
4125 font-size: .85rem;
4126 }
4127 .post-album-track-compact .pat-duration,
4128 .post-album-tracks .post-audio-track .pat-duration {
4129 font-size: .72rem;
4130 }
4131 /* Queue items in expand-sheet */
4132 .audio-sheet-queue-item { padding: .4rem .45rem; gap: .55rem; }
4133 .audio-sheet-queue-cover { width: 32px; height: 32px; }
4134 .audio-sheet-queue-title { font-size: .85rem; }
4135 .audio-sheet-queue-artist { font-size: .7rem; }
4136}
4137
4138/* External track (SoundCloud / YouTube / Spotify / etc) — klikbaar maar link-naar-platform */
4139.post-audio-external {
4140 display: flex;
4141 align-items: center;
4142 gap: .75rem;
4143 padding: .65rem .85rem;
4144 background: var(--paper-2, color-mix(in srgb, var(--ink) 4%, transparent));
4145 border: 1px solid var(--rule, rgba(0,0,0,.08));
4146 border-radius: 10px;
4147 margin: .75rem 0;
4148 text-decoration: none;
4149 color: var(--ink);
4150 transition: background .15s, border-color .15s;
4151}
4152.post-audio-external:hover {
4153 border-color: var(--accent);
4154 background: color-mix(in srgb, var(--accent) 5%, var(--paper-2, transparent));
4155}
4156.post-audio-external .pae-icon {
4157 flex-shrink: 0;
4158 width: 42px;
4159 height: 42px;
4160 border-radius: 8px;
4161 display: inline-flex;
4162 align-items: center;
4163 justify-content: center;
4164 background: var(--platform-color, #555);
4165 color: #fff;
4166 font-size: 1.2rem;
4167}
4168.post-audio-external .pae-icon-svg svg {
4169 width: 60%;
4170 height: 60%;
4171 fill: currentColor;
4172}
4173/* Per-platform vult de box net wat anders — brand-specifiek geoptimaliseerd */
4174.post-audio-external[data-platform="soundcloud"] .pae-icon-svg svg { width: 72%; height: auto; }
4175.post-audio-external[data-platform="spotify"] .pae-icon-svg svg { width: 72%; height: 72%; }
4176.post-audio-external[data-platform="youtube"] .pae-icon-svg svg { width: 68%; height: auto; }
4177.post-audio-external[data-platform="bandcamp"] .pae-icon-svg svg { width: 62%; height: auto; }
4178.post-audio-external[data-platform="apple"] .pae-icon-svg svg { width: 58%; height: 58%; }
4179.post-audio-external[data-platform="tidal"] .pae-icon-svg svg { width: 68%; height: auto; }
4180.post-audio-external[data-platform="deezer"] .pae-icon-svg svg { width: 65%; height: auto; }
4181.post-audio-external[data-platform="mixcloud"] .pae-icon-svg svg { width: 75%; height: auto; }
4182.post-audio-external[data-platform="soundcloud"] .pae-icon { background: #ff5500; }
4183.post-audio-external[data-platform="spotify"] .pae-icon { background: #1db954; }
4184.post-audio-external[data-platform="youtube"] .pae-icon { background: #ff0000; }
4185.post-audio-external[data-platform="bandcamp"] .pae-icon { background: #1da0c3; }
4186.post-audio-external[data-platform="apple"] .pae-icon { background: #fa243c; }
4187.post-audio-external[data-platform="tidal"] .pae-icon { background: #000; }
4188.post-audio-external[data-platform="deezer"] .pae-icon { background: #a238ff; }
4189.post-audio-external[data-platform="mixcloud"] .pae-icon { background: #314359; }
4190.post-audio-external[data-platform="other"] .pae-icon { background: #555; }
4191.post-audio-external .pae-meta {
4192 flex: 1;
4193 min-width: 0;
4194 display: flex;
4195 flex-direction: column;
4196 gap: 2px;
4197}
4198.post-audio-external .pae-title {
4199 display: block;
4200 font-weight: 600;
4201 overflow: hidden;
4202 text-overflow: ellipsis;
4203 white-space: nowrap;
4204 color: var(--ink);
4205}
4206.post-audio-external .pae-platform {
4207 display: block;
4208 font-size: .78rem;
4209 opacity: .65;
4210 text-transform: capitalize;
4211}
4212.post-audio-external .pae-go {
4213 flex-shrink: 0;
4214 opacity: .5;
4215 font-size: 1.1rem;
4216}
4217
4218/* =========================================================================
4219 v9.0 — Video player (inline)
4220 ========================================================================= */
4221
4222.post-video-figure {
4223 margin: 1.25rem 0;
4224 max-width: 100%;
4225}
4226
4227.post-video {
4228 display: block;
4229 width: 100%;
4230 max-width: 100%;
4231 height: auto;
4232 border-radius: 10px;
4233 background: #000;
4234 box-shadow: 0 4px 20px rgba(0,0,0,.15);
4235}
4236
4237.post-video-caption {
4238 margin-top: .5rem;
4239 font-size: .88rem;
4240 color: var(--ink-muted, color-mix(in srgb, var(--ink) 60%, transparent));
4241 text-align: center;
4242 line-height: 1.5;
4243}
4244
4245.post-video-caption strong {
4246 display: inline;
4247 font-weight: 600;
4248 color: var(--ink);
4249}
4250
4251@media (max-width: 640px) {
4252 .post-video-figure { margin: .75rem -.5rem; }
4253 .post-video { border-radius: 6px; }
4254}
4255
4256/* v9.3 — Floating "Bewerken" knop voor album-blokken in de post-editor.
4257 Verschijnt bij hover over een .post-album binnen #visual en wordt via JS
4258 geplaatst op de rechterbovenhoek van het blok. Niet in de opgeslagen HTML. */
4259.pcms-album-edit-overlay {
4260 position: absolute;
4261 z-index: 1000;
4262 transform: translateX(-100%);
4263 display: inline-flex;
4264 align-items: center;
4265 gap: .35rem;
4266 padding: .35rem .7rem;
4267 background: var(--accent, #c2410c);
4268 color: #fff;
4269 border: none;
4270 border-radius: 6px;
4271 font-size: .82rem;
4272 font-weight: 600;
4273 cursor: pointer;
4274 box-shadow: 0 4px 12px rgba(0, 0, 0, .18);
4275 transition: transform .12s ease, box-shadow .12s ease;
4276}
4277.pcms-album-edit-overlay:hover {
4278 transform: translateX(-100%) translateY(-1px);
4279 box-shadow: 0 6px 16px rgba(0, 0, 0, .24);
4280}
4281.pcms-album-edit-overlay:active {
4282 transform: translateX(-100%) translateY(0);
4283 box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
4284}
4285
4286/* v9.3 — Drag-and-drop in de album-builder selected-lijst */
4287.ab-selected-row { cursor: default; }
4288.ab-selected-row .ab-drag-handle {
4289 display: inline-flex;
4290 align-items: center;
4291 justify-content: center;
4292 width: 18px;
4293 height: 100%;
4294 color: color-mix(in srgb, currentColor 40%, transparent);
4295 cursor: grab;
4296 user-select: none;
4297 font-size: .9rem;
4298 letter-spacing: -2px;
4299 flex-shrink: 0;
4300}
4301.ab-selected-row:hover .ab-drag-handle {
4302 color: color-mix(in srgb, currentColor 70%, transparent);
4303}
4304.ab-selected-row.is-dragging {
4305 opacity: .35;
4306 cursor: grabbing;
4307}
4308.ab-selected-row.is-dragging .ab-drag-handle { cursor: grabbing; }
4309/* Drop-indicator lijnen boven/onder de target rij */
4310.ab-selected-row.is-drag-target-before {
4311 box-shadow: 0 -2px 0 0 var(--accent, #c2410c) inset, 0 2px 0 0 var(--accent, #c2410c);
4312 /* Gebruik outline voor cross-browser zichtbaarheid */
4313 position: relative;
4314}
4315.ab-selected-row.is-drag-target-before::before {
4316 content: "";
4317 position: absolute;
4318 top: -1px; left: 0; right: 0;
4319 height: 2px;
4320 background: var(--accent, #c2410c);
4321 pointer-events: none;
4322}
4323.ab-selected-row.is-drag-target-after::after {
4324 content: "";
4325 position: absolute;
4326 bottom: -1px; left: 0; right: 0;
4327 height: 2px;
4328 background: var(--accent, #c2410c);
4329 pointer-events: none;
4330}
4331.ab-selected-row.is-drag-target-after { position: relative; }
4332
4333/* v9.3 — Playlist fallback states (missing of empty playlist reference in post) */
4334.post-playlist-missing, .post-playlist-empty {
4335 padding: 1rem;
4336 margin: .75rem 0;
4337 background: color-mix(in srgb, var(--accent, #c2410c) 8%, transparent);
4338 border: 1px dashed color-mix(in srgb, var(--accent, #c2410c) 30%, transparent);
4339 border-radius: 8px;
4340 font-size: .9rem;
4341}
4342.post-playlist-missing em, .post-playlist-empty em {
4343 opacity: .8;
4344}
4345
4346/* v9.3 — Install-app footer-knop */
4347.site-footer-install {
4348 display: flex;
4349 justify-content: center;
4350 padding: 1rem 1rem 1.25rem;
4351 border-top: 1px solid color-mix(in srgb, currentColor 8%, transparent);
4352 margin-top: .5rem;
4353}
4354
4355/* v9.4 — Cooler install-knop: gradient + shimmer + perfect centering.
4356 Twee kleur-stops voor diepte, animated shimmer-streep om aandacht te trekken,
4357 icon perfect verticaal gecentreerd via flex (was: net iets te hoog tov tekst). */
4358.install-app-btn {
4359 position: relative;
4360 display: inline-flex;
4361 align-items: center;
4362 justify-content: center;
4363 gap: .55rem;
4364 padding: .8rem 1.6rem;
4365 background: linear-gradient(135deg,
4366 var(--accent, #c2410c),
4367 color-mix(in srgb, var(--accent, #c2410c) 80%, #000));
4368 color: #fff;
4369 border: none;
4370 border-radius: 999px;
4371 font: inherit;
4372 font-weight: 600;
4373 font-size: .95rem;
4374 line-height: 1;
4375 letter-spacing: .01em;
4376 cursor: pointer;
4377 overflow: hidden;
4378 isolation: isolate;
4379 box-shadow:
4380 0 1px 0 rgba(255,255,255,.15) inset,
4381 0 -2px 0 rgba(0,0,0,.1) inset,
4382 0 4px 14px color-mix(in srgb, var(--accent, #c2410c) 40%, transparent),
4383 0 1px 3px rgba(0,0,0,.18);
4384 transition:
4385 transform .15s cubic-bezier(.4, 0, .2, 1),
4386 box-shadow .2s ease,
4387 filter .15s ease;
4388}
4389.install-app-btn svg {
4390 flex-shrink: 0;
4391 /* subtle bounce-on-hover trigger, separate animation */
4392 transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
4393}
4394.install-app-btn span {
4395 line-height: 1;
4396}
4397
4398/* Shimmer-streep die langzaam over de knop loopt — "alive" effect */
4399.install-app-btn::before {
4400 content: "";
4401 position: absolute;
4402 top: 0;
4403 left: -100%;
4404 width: 60%;
4405 height: 100%;
4406 background: linear-gradient(110deg,
4407 transparent 30%,
4408 rgba(255,255,255,.25) 50%,
4409 transparent 70%);
4410 z-index: -1;
4411 animation: pcmsInstallShimmer 4s ease-in-out infinite;
4412 pointer-events: none;
4413}
4414@keyframes pcmsInstallShimmer {
4415 0%, 35% { left: -100%; }
4416 65%, 100% { left: 200%; }
4417}
4418
4419.install-app-btn:hover {
4420 transform: translateY(-2px) scale(1.02);
4421 filter: brightness(1.06);
4422 box-shadow:
4423 0 1px 0 rgba(255,255,255,.2) inset,
4424 0 -2px 0 rgba(0,0,0,.1) inset,
4425 0 8px 24px color-mix(in srgb, var(--accent, #c2410c) 55%, transparent),
4426 0 2px 6px rgba(0,0,0,.2);
4427}
4428.install-app-btn:hover svg {
4429 transform: translateY(-2px);
4430}
4431.install-app-btn:active {
4432 transform: translateY(0) scale(.98);
4433 transition-duration: .05s;
4434}
4435.install-app-btn:focus-visible {
4436 outline: 2px solid var(--accent, #c2410c);
4437 outline-offset: 3px;
4438}
4439
4440/* Reduced motion: shimmer uit, alleen statisch */
4441@media (prefers-reduced-motion: reduce) {
4442 .install-app-btn::before { animation: none; left: -100%; }
4443 .install-app-btn:hover { transform: none; }
4444 .install-app-btn:hover svg { transform: none; }
4445}
4446
4447/* Install-instructions modal */
4448.install-modal {
4449 position: fixed;
4450 inset: 0;
4451 z-index: 10000;
4452 display: flex;
4453 align-items: center;
4454 justify-content: center;
4455 padding: 1rem;
4456}
4457.install-modal-backdrop {
4458 position: absolute;
4459 inset: 0;
4460 background: rgba(0,0,0,.55);
4461 backdrop-filter: blur(3px);
4462}
4463.install-modal-panel {
4464 position: relative;
4465 z-index: 1;
4466 background: var(--paper);
4467 color: var(--ink);
4468 border: 1px solid var(--rule);
4469 border-radius: 14px;
4470 padding: 1.5rem;
4471 max-width: 440px;
4472 width: 100%;
4473 max-height: 90vh;
4474 overflow-y: auto;
4475 box-shadow: 0 20px 60px rgba(0,0,0,.4);
4476}
4477.install-modal-panel h3 { font-size: 1.15rem; color: var(--ink); }
4478.install-modal-panel h4 {
4479 margin: 1rem 0 .4rem;
4480 font-size: .92rem;
4481 letter-spacing: .03em;
4482 text-transform: uppercase;
4483 opacity: .7;
4484 color: var(--ink);
4485}
4486.install-modal-panel p { color: var(--ink); }
4487.install-steps {
4488 margin: 0;
4489 padding-left: 1.35rem;
4490 display: flex;
4491 flex-direction: column;
4492 gap: .45rem;
4493 font-size: .95rem;
4494 line-height: 1.45;
4495 color: var(--ink);
4496}
4497.install-steps li::marker { color: var(--accent); font-weight: 700; }
4498.install-apk-block {
4499 margin-top: 1.25rem;
4500 padding-top: 1rem;
4501 border-top: 1px dashed var(--rule);
4502}
4503.install-apk-link {
4504 display: inline-flex;
4505 align-items: center;
4506 margin-top: .4rem;
4507 padding: .6rem 1rem;
4508 background: var(--accent);
4509 color: #fff;
4510 border-radius: 8px;
4511 text-decoration: none;
4512 font-weight: 600;
4513}
4514.install-apk-link:hover { filter: brightness(1.08); }
4515.install-modal-actions {
4516 display: flex;
4517 justify-content: flex-end;
4518 margin-top: 1.25rem;
4519}
4520.install-modal-actions .btn {
4521 padding: .5rem 1rem;
4522 background: var(--paper-2);
4523 border: 1px solid var(--rule);
4524 border-radius: 8px;
4525 color: var(--ink);
4526 cursor: pointer;
4527 font: inherit;
4528 font-weight: 500;
4529}
4530.install-modal-actions .btn:hover {
4531 background: color-mix(in srgb, var(--accent) 10%, var(--paper-2));
4532 border-color: var(--accent);
4533 color: var(--accent);
4534}
4535
4536@media (max-width: 520px) {
4537 .install-modal-panel { padding: 1.2rem; }
4538 .install-app-btn { width: 100%; justify-content: center; }
4539}
4540
4541/* v9.3 — Install-modal: choice-blocks met voor/nadelen */
4542.install-choice {
4543 margin-top: 1.25rem;
4544 padding: 1rem;
4545 border: 1px solid color-mix(in srgb, currentColor 15%, transparent);
4546 border-radius: 10px;
4547 background: color-mix(in srgb, currentColor 3%, transparent);
4548}
4549.install-choice + .install-choice { margin-top: 1rem; }
4550.install-choice h4 {
4551 margin: 0 0 .75rem;
4552 font-size: 1rem;
4553 letter-spacing: 0;
4554 text-transform: none;
4555 opacity: 1;
4556}
4557.install-pros-cons {
4558 display: flex;
4559 gap: 1rem;
4560 margin: .5rem 0 1rem;
4561}
4562.install-pros,
4563.install-cons {
4564 flex: 1;
4565 min-width: 0;
4566 font-size: .85rem;
4567 line-height: 1.45;
4568}
4569.install-pros strong,
4570.install-cons strong {
4571 display: block;
4572 margin-bottom: .35rem;
4573 font-size: .82rem;
4574 letter-spacing: .02em;
4575}
4576.install-pros strong { color: #16a34a; }
4577.install-cons strong { color: #dc2626; }
4578.install-pros ul,
4579.install-cons ul {
4580 margin: 0;
4581 padding-left: 1.1rem;
4582 display: flex;
4583 flex-direction: column;
4584 gap: .25rem;
4585}
4586.install-pros li::marker { color: #16a34a; }
4587.install-cons li::marker { color: #dc2626; }
4588
4589.install-choice-cta {
4590 display: inline-flex;
4591 align-items: center;
4592 justify-content: center;
4593 gap: .35rem;
4594 margin-top: .5rem;
4595 padding: .7rem 1.1rem;
4596 background: var(--accent, #c2410c);
4597 color: #fff;
4598 border: none;
4599 border-radius: 8px;
4600 text-decoration: none;
4601 font: inherit;
4602 font-weight: 600;
4603 font-size: .95rem;
4604 cursor: pointer;
4605 transition: filter .12s ease;
4606}
4607.install-choice-cta:hover { filter: brightness(1.08); }
4608.install-choice-note {
4609 margin: .5rem 0 0;
4610 padding: .6rem .8rem;
4611 background: color-mix(in srgb, currentColor 4%, transparent);
4612 border-left: 3px solid var(--accent, #c2410c);
4613 border-radius: 4px;
4614 font-size: .9rem;
4615 line-height: 1.45;
4616}
4617
4618@media (max-width: 520px) {
4619 .install-pros-cons { flex-direction: column; gap: .75rem; }
4620}
4621
4622/* v9.4 — Soft fade-overgang tussen posts bij navigatie.
4623 Fade-out is rustig (450ms): oude content vervaagt geleidelijk terwijl
4624 de scroll-naar-top loopt. Fade-in is snel (180ms) met een lichte blur-
4625 onscherp → scherp animatie zodat de nieuwe content niet abrupt verschijnt. */
4626#pcms-main {
4627 transition: opacity .45s ease-out;
4628}
4629#pcms-main.is-pcms-transitioning-out {
4630 opacity: 0;
4631}
4632#pcms-main.is-pcms-transitioning-in {
4633 opacity: 0;
4634 filter: blur(6px);
4635 animation: pcmsFadeIn .18s ease-out forwards;
4636 will-change: opacity, filter;
4637}
4638@keyframes pcmsFadeIn {
4639 from { opacity: 0; filter: blur(6px); }
4640 to { opacity: 1; filter: blur(0); }
4641}
4642
4643/* Respecteer reduced-motion voorkeur (iOS/Android accessibility setting) */
4644@media (prefers-reduced-motion: reduce) {
4645 #pcms-main {
4646 transition: opacity .15s ease-out;
4647 }
4648 #pcms-main.is-pcms-transitioning-in {
4649 filter: none;
4650 animation: none;
4651 opacity: 1;
4652 }
4653}
4654
4655/* === Fediverse interactions — inherits the native .comment styling === */
4656.post-fediverse .fedi-stats { display: flex; gap: .45rem; margin: .35rem 0 1.5rem; align-items: center; }
4657.post-fediverse .fedi-stat {
4658 display: inline-flex; align-items: center; gap: .4rem;
4659 padding: .32rem .7rem; border-radius: 999px; font-size: .85rem; line-height: 1;
4660 font-variant-numeric: tabular-nums;
4661 color: var(--ink-muted); background: transparent;
4662 border: 1px solid var(--rule);
4663}
4664.post-fediverse .fedi-stat svg { width: 15px; height: 15px; }
4665.post-fediverse .fedi-stat-btn { cursor: pointer; font: inherit; line-height: 1; transition: color .15s, border-color .15s, background .15s; }
4666.post-fediverse .fedi-stat-btn:hover { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, var(--rule)); background: var(--accent-tint); }
4667.post-fediverse .fedi-stat-btn:hover svg { fill: color-mix(in srgb, var(--accent) 22%, transparent); }
4668.post-fediverse .fedi-handle { color: var(--ink-soft, #888); font-size: .82rem; }
4669.post-fediverse .comment-content p { margin: .2rem 0; }
4670.post-fediverse .comment-content p:first-child { margin-top: 0; }
4671.post-fediverse .comment-content p:last-child { margin-bottom: 0; }
4672/* reply toggle: a plain "Reageer" action like the comment buttons (no triangle) */
4673.post-fediverse .fedi-reply-toggle { list-style: none; cursor: pointer; display: inline-block; }
4674.post-fediverse .fedi-reply-toggle::-webkit-details-marker { display: none; }
4675.post-fediverse details[open] .fedi-reply-toggle { margin-bottom: .5rem; }
4676
4677/* Reply-via-fediverse CTA on post pages */
4678.post-fediverse-cta { margin: 1.75rem 0; }
4679.fedi-remote-reply-btn { display: inline-flex; align-items: center; gap: .45rem; }
4680.post-fediverse-cta .fedi-remote-reply-btn {
4681 border: 1px solid color-mix(in srgb, var(--accent, #888) 55%, transparent);
4682 background: color-mix(in srgb, var(--accent, #888) 10%, transparent);
4683 color: var(--ink, inherit); border-radius: 999px; padding: .5rem 1.05rem;
4684 font-weight: 600; cursor: pointer; transition: background .15s ease;
4685}
4686.post-fediverse-cta .fedi-remote-reply-btn:hover { background: color-mix(in srgb, var(--accent, #888) 22%, transparent); }
4687.post-fediverse-cta .fedi-remote-reply-btn svg { color: var(--accent, currentColor); }
4688.post-fediverse .comment-actions .fedi-remote-reply-btn { gap: .3rem; }
4689
4690/* Inline "reply via fediverse" address form (replaces the browser prompt) */
4691.fedi-remote-form {
4692 position: absolute; z-index: 60; display: inline-flex; align-items: center; gap: .4rem;
4693 padding: .4rem; border-radius: 999px;
4694 background: var(--paper-2, var(--paper, #fff));
4695 border: 1px solid color-mix(in srgb, var(--ink, #000) 12%, transparent);
4696 box-shadow: 0 10px 30px rgba(0,0,0,.28);
4697}
4698.fedi-remote-form input {
4699 height: 2.2rem; padding: 0 .9rem; border-radius: 999px; font: inherit; min-width: 230px;
4700 border: 1px solid color-mix(in srgb, var(--ink, #000) 18%, transparent);
4701 background: color-mix(in srgb, var(--ink, #000) 4%, transparent); color: var(--ink, #000);
4702}
4703.fedi-remote-form input::placeholder { color: var(--ink-soft, #999); }
4704.fedi-remote-form input:focus { outline: none; border-color: color-mix(in srgb, var(--accent, #888) 70%, transparent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #888) 22%, transparent); }
4705.fedi-remote-form .fedi-remote-go {
4706 height: 2.2rem; min-width: 2.2rem; padding: 0 .85rem; border-radius: 999px;
4707 display: inline-flex; align-items: center; justify-content: center; font-size: 1rem;
4708}
4709.fedi-remote-form .fedi-remote-cancel { background: none; border: none; color: var(--ink-soft, #888); cursor: pointer; font-size: 1.1rem; line-height: 1; padding: .25rem .35rem; }
4710.fedi-remote-form .fedi-remote-cancel:hover { color: var(--ink, #000); }
4711
4712/* ── NSFW / sensitive content — blur + click to reveal ───────────────── */
4713.nsfw-media { position: relative; }
4714.nsfw-veil {
4715 position: absolute; inset: 0; z-index: 4; cursor: pointer; border-radius: inherit;
4716 display: flex; flex-direction: column; align-items: center; justify-content: center;
4717 gap: .5rem; padding: .75rem; text-align: center;
4718 background: color-mix(in srgb, var(--paper, #14141a) 50%, transparent);
4719 backdrop-filter: blur(22px) saturate(.6); -webkit-backdrop-filter: blur(22px) saturate(.6);
4720}
4721.nsfw-media.is-shown > .nsfw-veil { display: none; }
4722.nsfw-veil-label { font-weight: 700; font-size: .82rem; color: var(--ink, #f3f1ea); text-shadow: 0 1px 2px rgba(0,0,0,.5); }
4723.nsfw-veil-btn {
4724 font-size: .72rem; font-weight: 600; padding: .3rem .8rem; border-radius: 999px;
4725 border: 1px solid color-mix(in srgb, var(--ink, #fff) 55%, transparent);
4726 background: color-mix(in srgb, var(--paper, #000) 35%, transparent); color: var(--ink, #f3f1ea);
4727}
4728/* Post page: blur cover + body behind a content-warning banner until revealed */
4729.nsfw-gate .post-cover,
4730.nsfw-gate .post-content { filter: blur(26px); pointer-events: none; user-select: none; transition: filter .2s ease; }
4731.nsfw-gate.is-shown .post-cover,
4732.nsfw-gate.is-shown .post-content { filter: none; pointer-events: auto; user-select: auto; }
4733.nsfw-banner {
4734 display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; margin: 0 0 1.5rem;
4735 padding: .8rem 1rem; border-radius: 12px;
4736 border: 1px solid color-mix(in srgb, var(--accent, #e8b04b) 45%, transparent);
4737 background: color-mix(in srgb, var(--accent, #e8b04b) 9%, transparent);
4738}
4739.nsfw-gate.is-shown .nsfw-banner { display: none; }
4740.nsfw-banner-icon { font-size: 1.2rem; }
4741.nsfw-banner-text { font-weight: 600; font-size: .92rem; color: var(--ink); }
4742.nsfw-banner-btn {
4743 margin-left: auto; cursor: pointer; font: inherit; font-size: .82rem; font-weight: 600;
4744 padding: .4rem 1rem; border-radius: 999px; border: 0;
4745 background: var(--accent, #e8b04b); color: #1a1205;
4746}
Note: See TracBrowser for help on using the repository browser.