source: Klonkt/src/assets/css/style.css@ 2d2fd8c

main
Last change on this file since 2d2fd8c was 2d2fd8c, checked in by Bart <bart@…>, 3 weeks ago

Tijdlijn | Grid | Lezen: de leesweergave krijgt een ingang

De leesweergave bestond wel maar was alleen te bereiken door /read in te tikken.
Nu staat ze als derde optie in dezelfde pil.

Een <a>, geen <button>, en met opzet NIET de klasse view-switch-btn: de
gedelegeerde klik in shell.ejs pakt alles met die klasse op, zet
body[data-feed-view] erop en springt op niet-feedpagina's terug naar home. Die
had deze link opgegeten.

Door er een link naartoe te leggen kwamen twee fouten boven die er al zaten:

  1. De route gaf ELKE htmx-aanvraag één kaal artikel terug, want de leesmodule had ?partial=1 geleend -- en dat betekent op deze site al iets anders: "de pagina zonder de schil". Een gebooste link naar /read schoof dus één artikel in #pcms-main: geen stroom, geen script. De module vraagt nu ?fragment=1, en al het andere gaat naar pages/read waar renderPage zelf over de schil beslist.
  1. PAGE_CLASSES in shell.ejs is een witte lijst, en 'on-read' stond er niet in. Bij een htmx-navigatie werd de class dus weggefilterd en sloeg ELKE regel van de leesweergave (.on-read ...) niet aan: geen schermhoge berichten, geen snappen, geen wegschuivende balken. Bij intikken ging het goed, want dan zet de shell de class zelf -- vandaar dat het onzichtbaar bleef.

Beide nagelopen in de browser: de pil navigeert, on-read staat er, min-height is
de schermhoogte, snappen staat aan, en de opgeslagen feed-view blijft ongemoeid.

MOD_V naar 3 (read.js) en style.css naar v68 (nieuwe selector).

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

  • Property mode set to 100644
File size: 150.1 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.view-switch-link {
2357 display: inline-flex;
2358 align-items: center;
2359 gap: .4rem;
2360 padding: .35rem .85rem; /* was .55rem 1rem */
2361 min-height: 32px; /* was 44px */
2362 background: transparent;
2363 border: 1px solid var(--rule);
2364 border-radius: 999px;
2365 color: var(--ink-muted);
2366 font-family: var(--font-ui);
2367 font-size: .82rem; /* was .85rem */
2368 cursor: pointer;
2369 transition: all .15s;
2370}
2371.view-switch-btn:hover,
2372.view-switch-link:hover {
2373 color: var(--ink);
2374 border-color: var(--ink-muted);
2375}
2376/* Actieve state: puur afgeleid van body[data-feed-view]. Geen .is-active class meer.
2377 Niet op de Archive-pagina: daar is geen "huidige" timeline/grid-keuze, dus beide
2378 knoppen blijven neutraal (grijs). */
2379/* Actieve Tijdlijn/Grid-state wordt nu gestuurd via [aria-selected="true"] (gezet
2380 door syncAria, die óók op htmx:afterSettle draait) i.p.v. body[data-feed-view].
2381 Reden: body-class/attribuut-CSS pakte niet betrouwbaar na een htmx-OOB-swap;
2382 een element-attribuut wel. De witte active-regel staat in shared-styles. */
2383.view-switch-btn .icon { width: 1rem; height: 1rem; }
2384
2385/* -------- FEED TOGGLE VIA BODY --------
2386 Grid-modus werkt op de feed (home, cirkel). Het ARCHIEF negeert de grid-keuze
2387 bewust: dat is altijd de chronologische jaar/maand-lijst (de switcher is daar
2388 grijs en springt bij klik terug naar de feed). Post-pagina's tonen de
2389 feed-timeline article sowieso altijd. Alle andere body-classes negeren
2390 data-feed-view en houden timeline visible. */
2391body.on-home[data-feed-view="grid"] .feed-timeline,
2392body.on-home[data-feed-view="grid"] .pagination,
2393body.on-home[data-feed-view="grid"] .related-posts,
2394body.on-home[data-feed-view="grid"] .article-footer,
2395body.on-cirkel[data-feed-view="grid"] .feed-timeline {
2396 display: none !important;
2397}
2398/* Grid-sectie alleen zichtbaar op de feed in grid-mode (NIET op archief) */
2399.feed-grid { display: none; }
2400body.on-home[data-feed-view="grid"] .feed-grid,
2401body.on-cirkel[data-feed-view="grid"] .feed-grid { display: block; }
2402
2403/* -------- GRID VIEW TILES (Instagram-stijl) -------- */
2404.feed-grid {
2405 padding: 1rem 0 2rem;
2406}
2407.grid-tiles {
2408 display: grid;
2409 gap: 4px;
2410 grid-template-columns: repeat(2, 1fr);
2411}
2412.grid-tile {
2413 position: relative;
2414 display: block;
2415 aspect-ratio: 1;
2416 background-size: cover;
2417 background-position: center;
2418 background-color: var(--paper-2);
2419 overflow: hidden;
2420 text-decoration: none;
2421 color: var(--ink);
2422 transition: transform .2s;
2423 cursor: pointer;
2424 -webkit-tap-highlight-color: rgba(0,0,0,.1);
2425}
2426
2427/* Transparent covers (PNG logos etc.) sit on white so they don't blend into a dark
2428 theme. The white is on the IMG, so the tile's accent-gradient placeholder shows
2429 while the image is still loading. */
2430.post-cover img,
2431.post-list-cover img,
2432.grid-tile-img { background-color: #fff; }
2433/* Accent-gradient placeholder shown while the cover image loads (the image fades in
2434 over it), instead of a white flash on cover tiles. */
2435.grid-tile:not(.grid-tile-gradient) {
2436 background-image: linear-gradient(135deg,
2437 color-mix(in srgb, var(--accent, #888) 22%, var(--paper-2, var(--paper))) 0%,
2438 color-mix(in srgb, var(--accent, #888) 6%, var(--paper-2, var(--paper))) 100%);
2439}
2440/* Cover as a real <img> (not background-image): browsers downsample <img> with the
2441 high-quality image pipeline, so high-res line-art covers don't go jagged when shrunk.
2442 Fades in on load (.is-loading removed) so the placeholder shows meanwhile. */
2443.grid-tile-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; transition: opacity .4s ease; }
2444.grid-tile-img.is-loading { opacity: 0; }
2445/* Audio tile (Shaer, Robins vraag 30-7): the waveform PNG is white on
2446 transparent and floats OVER the tile's own hue gradient, so every audio
2447 post keeps its color and gets its shape. Wave and title each get their
2448 own band (wave upper, title lower): centering both stacked them right
2449 through each other (Robins schermafdruk). */
2450.grid-tile-img.grid-tile-wave {
2451 background-color: transparent;
2452 object-fit: contain;
2453 /* explicit box, not auto: an absolutely positioned img falls back to its
2454 intrinsic size when width/height are auto, collapsing the band */
2455 top: 8%; left: 8%; right: auto; bottom: auto;
2456 width: 84%; height: 46%;
2457 opacity: .85;
2458}
2459.grid-tile-audio .grid-tile-title { position: absolute; left: 10%; right: 10%; top: 60%; }
2460.grid-tile-audio .grid-tile-gradient-src { position: absolute; left: 10%; right: 10%; top: 76%; }
2461/* Cover videos are decorative, not players: let clicks + right-click pass through to the
2462 tile link so you get the normal link menu (not the browser's <video> menu/controls).
2463 Autoplay is independent of pointer-events, so the video still plays. */
2464video.grid-tile-img,
2465.post-list-cover video,
2466.post-cover video { pointer-events: none; }
2467.grid-tile:hover { transform: scale(0.98); }
2468.grid-tile-overlay {
2469 position: absolute;
2470 inset: 0;
2471 padding: .6rem;
2472 display: flex;
2473 flex-direction: column;
2474 justify-content: flex-end;
2475 align-items: flex-start;
2476 background: linear-gradient(to top, rgba(0,0,0,.65) 0%, rgba(0,0,0,0) 50%);
2477 opacity: 0;
2478 transition: opacity .2s;
2479 pointer-events: none; /* klik moet naar de <a> eronder gaan, niet naar de overlay */
2480}
2481/* Bron-site (cirkel-feed): toont bij hover "van <site>" onder de titel. */
2482/* Source label: small text that wraps to 2 lines if needed, with a big chain icon
2483 beside it (the text was 1.44rem — bigger than the title — and overflowed on mobile). */
2484.grid-tile-overlay-src {
2485 color: #fff; opacity: .85;
2486 font-size: .72rem; line-height: 1.2; margin-top: .25rem;
2487 display: flex; align-items: center; gap: .3rem; width: 100%;
2488}
2489.grid-tile-overlay-src::before { content: "⛓"; font-size: 1.3rem; line-height: 1; flex: 0 0 auto; }
2490.grid-tile-gradient-src {
2491 margin-top: .35rem; font-size: .72rem; line-height: 1.2; opacity: .85;
2492 color: var(--ink-soft);
2493 display: flex; align-items: center; gap: .3rem; width: 100%;
2494}
2495.grid-tile-gradient-src::before { content: "⛓"; font-size: 1.3rem; line-height: 1; flex: 0 0 auto; }
2496.grid-tile-overlay strong {
2497 color: #fff;
2498 font-family: var(--font-display);
2499 font-size: .9rem;
2500 font-weight: 500;
2501 line-height: 1.15;
2502 display: -webkit-box;
2503 -webkit-line-clamp: 3;
2504 -webkit-box-orient: vertical;
2505 overflow: hidden;
2506}
2507@media (hover: hover) {
2508 .grid-tile:hover .grid-tile-overlay { opacity: 1; }
2509}
2510@media (hover: none) {
2511 /* Op touch-devices altijd overlay tonen zodat titels zichtbaar zijn */
2512 .grid-tile-overlay { opacity: 1; background: linear-gradient(to top, rgba(0,0,0,.7) 0%, rgba(0,0,0,0) 70%); }
2513}
2514
2515.grid-tile-gradient {
2516 background-image: none;
2517 background-color: hsl(var(--tile-hue, 30), 40%, 85%);
2518 background-image: linear-gradient(135deg, hsl(var(--tile-hue, 30), 45%, 88%), hsl(calc(var(--tile-hue, 30) + 30), 35%, 75%));
2519 display: flex;
2520 flex-direction: column;
2521 align-items: center;
2522 justify-content: center;
2523 padding: 1rem;
2524 text-align: center;
2525}
2526[data-theme="dark"] .grid-tile-gradient,
2527.grid-tile-gradient[data-theme="dark"] {
2528 background-image: linear-gradient(135deg, hsl(var(--tile-hue, 30), 30%, 18%), hsl(calc(var(--tile-hue, 30) + 30), 25%, 12%));
2529}
2530.grid-tile-title {
2531 font-family: var(--font-display);
2532 font-size: 1rem;
2533 font-weight: 500;
2534 color: var(--ink);
2535 line-height: 1.2;
2536 display: -webkit-box;
2537 -webkit-line-clamp: 4;
2538 -webkit-box-orient: vertical;
2539 overflow: hidden;
2540 z-index: 1;
2541 /* Federated link posts can have a long bare URL as their title — break it so it wraps
2542 inside the tile and clamps cleanly instead of overflowing past both edges. */
2543 max-width: 100%;
2544 overflow-wrap: anywhere;
2545 word-break: break-word;
2546 hyphens: auto;
2547}
2548
2549.grid-tile-pin {
2550 position: absolute;
2551 top: .5rem;
2552 right: .5rem;
2553 display: inline-flex;
2554 align-items: center;
2555 gap: .25rem;
2556 padding: .2rem .55rem;
2557 background: var(--accent);
2558 color: #fff;
2559 border-radius: 999px;
2560 font-family: var(--font-ui);
2561 font-size: .65rem;
2562 font-weight: 700;
2563 text-transform: uppercase;
2564 letter-spacing: .06em;
2565 z-index: 3;
2566 box-shadow: 0 2px 6px rgba(0,0,0,.3);
2567 pointer-events: none;
2568}
2569.grid-tile-pin svg {
2570 width: .95em;
2571 height: .95em;
2572 margin-top: -1px;
2573}
2574/* Pinned/boosted tile: accent ring. An outline on the tile is painted UNDER the absolute
2575 cover <img>, so draw the ring as a pseudo-element overlay ABOVE the image (z-index above
2576 the img, below the corner badges + nsfw veil). */
2577.grid-tile.is-pinned { position: relative; z-index: 1; }
2578.grid-tile.is-pinned::after {
2579 content: '';
2580 position: absolute;
2581 inset: 0;
2582 border: 3px solid var(--accent);
2583 border-radius: inherit;
2584 pointer-events: none;
2585 z-index: 1;
2586}
2587.grid-tile-type {
2588 position: absolute;
2589 top: .4rem;
2590 left: .4rem;
2591 padding: .15rem .5rem;
2592 background: rgba(0,0,0,.55);
2593 color: #fff;
2594 border-radius: 999px;
2595 font-family: var(--font-ui);
2596 font-size: .6rem;
2597 font-weight: 600;
2598 text-transform: uppercase;
2599 letter-spacing: .05em;
2600 z-index: 2;
2601}
2602
2603@media (min-width: 600px) {
2604 .grid-tiles { grid-template-columns: repeat(3, 1fr); }
2605}
2606@media (min-width: 900px) {
2607 .grid-tiles { grid-template-columns: repeat(3, 1fr); gap: 8px; }
2608}
2609
2610/* -------- POST-TYPE SPECIFIEKE LAYOUTS -------- */
2611
2612/* Foto-post: beeld prominent, geen titel bovenaan, caption onder */
2613.feed-timeline[data-post-type="foto"] .post-title {
2614 font-size: 1.1rem;
2615 color: var(--ink-muted);
2616 font-weight: 400;
2617}
2618.feed-timeline[data-post-type="foto"] .post-cover {
2619 margin: 0 -1rem 1rem;
2620 border-radius: 0;
2621}
2622.feed-timeline[data-post-type="foto"] .post-cover img {
2623 width: 100%;
2624 border-radius: 0;
2625}
2626
2627/* Post-caption onder de cover */
2628.post-caption {
2629 font-family: var(--font-body);
2630 font-size: 1rem;
2631 color: var(--ink);
2632 line-height: 1.5;
2633 margin: 0 0 1.25rem;
2634 padding: 0 0 1rem;
2635 border-bottom: 1px solid var(--rule);
2636 white-space: pre-wrap;
2637}
2638.feed-timeline[data-post-type="foto"] .post-caption {
2639 font-size: 1.05rem;
2640 margin-top: -.5rem;
2641 padding-bottom: 1.25rem;
2642}
2643
2644/* Audio/video posts — type-chip helder, content eronder zoals normaal */
2645.feed-timeline[data-post-type="audio"] .post-title,
2646.feed-timeline[data-post-type="video"] .post-title {
2647 font-size: 1.5rem;
2648}
2649
2650@media (min-width: 768px) {
2651 .feed-timeline[data-post-type="foto"] .post-cover {
2652 margin: 0 0 1.5rem;
2653 border-radius: var(--radius);
2654 }
2655}
2656
2657/* -------- ADMIN EDIT-BUTTON op post-view (alleen zichtbaar voor ingelogde admin) -------- */
2658.post-edit-btn {
2659 position: absolute;
2660 top: 1rem;
2661 right: 1rem;
2662 display: inline-flex;
2663 align-items: center;
2664 justify-content: center;
2665 width: 44px;
2666 height: 44px;
2667 background: var(--paper);
2668 border: 1px solid var(--rule);
2669 border-radius: 50%;
2670 color: var(--ink-muted);
2671 text-decoration: none;
2672 box-shadow: 0 2px 8px rgba(0,0,0,.08);
2673 transition: background .15s, color .15s, transform .15s, border-color .15s;
2674 z-index: 10;
2675}
2676.post-edit-btn:hover {
2677 background: var(--accent);
2678 border-color: var(--accent);
2679 color: var(--paper);
2680 transform: scale(1.05);
2681}
2682.post-edit-btn .icon {
2683 width: 1.1rem;
2684 height: 1.1rem;
2685}
2686/* Zorg dat de article relative is zodat absolute positionering werkt */
2687.feed-timeline { position: relative; }
2688
2689@media (min-width: 768px) {
2690 .post-edit-btn {
2691 top: 1.5rem;
2692 right: 1.5rem;
2693 }
2694}
2695
2696/* ============================================================
2697 v8.0 — ACCENT SPAN + POST-TABLE (published posts)
2698 ============================================================ */
2699.post span.accent,
2700.post-content span.accent,
2701article span.accent,
2702page-container span.accent {
2703 color: var(--accent);
2704 font-weight: 500;
2705}
2706
2707.post-table,
2708article table.post-table {
2709 width: 100%;
2710 max-width: 100%;
2711 border-collapse: collapse;
2712 margin: 1.25rem 0;
2713 font-size: .95rem;
2714 display: block;
2715 overflow-x: auto;
2716 -webkit-overflow-scrolling: touch;
2717}
2718.post-table thead { background: color-mix(in srgb, var(--accent) 10%, transparent); }
2719.post-table th,
2720.post-table td {
2721 padding: .6rem .8rem;
2722 text-align: left;
2723 border: 1px solid var(--rule);
2724 vertical-align: top;
2725}
2726.post-table th {
2727 font-family: var(--font-ui);
2728 font-weight: 600;
2729 font-size: .88rem;
2730 color: var(--ink);
2731 letter-spacing: .02em;
2732}
2733.post-table tbody tr:nth-child(even) {
2734 background: color-mix(in srgb, var(--ink) 3%, transparent);
2735}
2736@media (min-width: 700px) {
2737 .post-table { display: table; overflow: visible; }
2738}
2739
2740/* ============================================================
2741 v8.0 fix — grid-cols picker (desktop only) + grid col overrides
2742 ============================================================ */
2743
2744/* Switcher-wrap bevat nu ook de cols-picker; layout side-by-side */
2745.view-switcher-wrap .container {
2746 display: flex;
2747 align-items: center;
2748 justify-content: center;
2749 gap: 1rem;
2750 flex-wrap: wrap;
2751}
2752
2753/* Solo / Cirkel scope-switcher (alleen in circle-modus) — segmented toggle, centraal.
2754 Hoge specificiteit (+ !important op tekst) zodat 'ie globale link-stijlen wint. */
2755.view-switcher-wrap .feed-scope {
2756 display: inline-flex;
2757 background: var(--paper-2);
2758 border: 1px solid var(--rule);
2759 border-radius: 999px;
2760 padding: 3px;
2761}
2762.view-switcher-wrap .feed-scope-btn {
2763 display: inline-flex;
2764 align-items: center;
2765 padding: .32rem .95rem;
2766 min-height: 30px;
2767 border: none !important;
2768 border-radius: 999px !important;
2769 background: transparent !important;
2770 color: var(--ink-muted) !important;
2771 font-family: var(--font-ui);
2772 font-size: .82rem;
2773 font-weight: 500 !important;
2774 text-decoration: none !important;
2775 cursor: pointer;
2776 transition: all .15s;
2777}
2778.view-switcher-wrap .feed-scope-btn:hover { color: var(--ink) !important; }
2779.view-switcher-wrap .feed-scope-btn.is-active {
2780 background: var(--ink) !important;
2781 color: var(--paper) !important;
2782}
2783
2784.grid-cols-picker {
2785 display: none; /* default hidden — desktop + grid-active maakt 'm zichtbaar */
2786 gap: 2px;
2787 padding: 0;
2788}
2789.grid-cols-btn {
2790 display: inline-flex;
2791 align-items: center;
2792 justify-content: center;
2793 min-width: 36px;
2794 height: 32px;
2795 padding: 0 .6rem;
2796 background: transparent;
2797 border: 1px solid var(--rule);
2798 color: var(--ink-muted);
2799 font-family: var(--font-ui);
2800 font-size: .85rem;
2801 font-weight: 500;
2802 cursor: pointer;
2803 transition: all .12s;
2804}
2805.grid-cols-btn:first-child { border-radius: 999px 0 0 999px; }
2806.grid-cols-btn:last-child { border-radius: 0 999px 999px 0; }
2807.grid-cols-btn:not(:first-child):not(:last-child) { border-left: none; border-right: none; }
2808.grid-cols-btn:hover { color: var(--ink); }
2809/* Active state puur via body[data-grid-cols] — geen is-active-class meer. */
2810body[data-grid-cols="2"] .grid-cols-btn[data-cols="2"],
2811body[data-grid-cols="3"] .grid-cols-btn[data-cols="3"],
2812body[data-grid-cols="4"] .grid-cols-btn[data-cols="4"] {
2813 background: var(--ink);
2814 color: var(--paper);
2815 border-color: var(--ink);
2816}
2817
2818/* Desktop + grid-view → toon cols-picker (op de home-feed; niet op archief) */
2819@media (min-width: 600px) {
2820 body.on-home[data-feed-view="grid"] .grid-cols-picker {
2821 display: inline-flex;
2822 }
2823}
2824
2825/* Kolom-overrides op desktop. Mobiel negeert dit (staat vast op 2). Geldt op ELKE
2826 feed met grid (home én cirkel/tag/type/user) — scope op .feed-grid .grid-tiles. */
2827@media (min-width: 600px) {
2828 body[data-grid-cols="2"] .feed-grid .grid-tiles { grid-template-columns: repeat(2, 1fr); }
2829 body[data-grid-cols="3"] .feed-grid .grid-tiles { grid-template-columns: repeat(3, 1fr); }
2830 body[data-grid-cols="4"] .feed-grid .grid-tiles { grid-template-columns: repeat(4, 1fr); }
2831}
2832
2833/* Gradient-tile: iets meer contrast voor light + dark mode zodat titel altijd leesbaar is */
2834.grid-tile-gradient {
2835 background-image: linear-gradient(135deg,
2836 hsl(var(--tile-hue, 30), 55%, 72%),
2837 hsl(calc(var(--tile-hue, 30) + 40), 45%, 60%));
2838}
2839[data-theme="dark"] .grid-tile-gradient {
2840 background-image: linear-gradient(135deg,
2841 hsl(var(--tile-hue, 30), 40%, 30%),
2842 hsl(calc(var(--tile-hue, 30) + 40), 30%, 18%));
2843}
2844.grid-tile-gradient .grid-tile-title {
2845 color: #fff;
2846 text-shadow: 0 1px 3px rgba(0,0,0,.25);
2847}
2848[data-theme="dark"] .grid-tile-gradient .grid-tile-title {
2849 color: #fff;
2850 text-shadow: 0 1px 2px rgba(0,0,0,.5);
2851}
2852
2853/* ============================================================
2854 v8.0.2 — COMPACT DESIGN OVERRIDES
2855 Tighter masthead, padding, margins overall. Profiel-header
2856 collapse/expand blijft zoals 'ie was.
2857 ============================================================ */
2858
2859/* Masthead: compacter */
2860.masthead { padding: calc(.55rem + var(--ios-safe-top, 0px)) 0 .55rem; }
2861.masthead-inner { gap: 1rem; }
2862.site-title { font-size: 1.25rem; }
2863.nav-link, .nav-btn { padding: .4rem .7rem; min-height: 2rem; font-size: .82rem; }
2864
2865/* Main content padding */
2866main { padding-top: 1rem; }
2867.page { padding-block: 1rem 1.75rem; }
2868
2869/* View switcher-bar strakker */
2870.view-switcher { padding: .4rem 0; gap: .3rem; }
2871.view-switch-btn { padding: .4rem .85rem; min-height: 38px; font-size: .8rem; }
2872.grid-cols-btn { min-width: 32px; height: 28px; padding: 0 .5rem; font-size: .8rem; }
2873
2874/* Post header spacing terug */
2875.post-header { margin: 0 0 1.25rem; }
2876.post-title { margin-bottom: .35rem; }
2877.post-meta { font-size: .78rem; }
2878.post-tags { margin-top: .6rem; gap: .3rem; }
2879.post-tag { font-size: .7rem; padding: .15rem .55rem; }
2880
2881/* Article footer + pagination compacter */
2882.article-footer { padding-top: 1.25rem; margin-top: 1.5rem; }
2883.pagination { padding-block: 1.25rem 2rem; margin-top: 1.5rem; }
2884.pagination-item { padding: .75rem .95rem; min-height: 4rem; }
2885.pagination-title { font-size: .95rem; }
2886
2887/* Site footer compacter */
2888.site-footer { padding: 1.25rem 0 calc(1.25rem + env(safe-area-inset-bottom, 0px)); margin-top: 2rem; font-size: .78rem; }
2889.site-footer-inner { gap: .75rem; }
2890
2891/* Profiel-header: full mode iets minder riant (compact mode blijft hetzelfde) */
2892.profile-header { padding: 1rem 0; }
2893.profile-photo { width: 72px; height: 72px; }
2894.profile-photo-fallback { font-size: 1.8rem; }
2895.profile-name { font-size: 1.2rem; }
2896.profile-bio { font-size: .85rem; margin-top: .15rem; }
2897.profile-links { margin-top: .5rem; gap: .4rem; }
2898.profile-links a,
2899.profile-links .profile-fedi-link { width: 32px; height: 32px; }
2900
2901@media (min-width: 768px) {
2902 .profile-header { padding: 1.35rem 0; }
2903 .profile-photo { width: 92px; height: 92px; }
2904 .profile-photo-fallback { font-size: 2.4rem; }
2905 .profile-name { font-size: 1.4rem; }
2906 .profile-bio { font-size: .95rem; }
2907 .profile-header-inner { gap: 1.1rem; }
2908 /* Compact-mode op desktop blijft klein zoals we hadden afgesproken */
2909 .on-post .profile-photo,
2910 .on-special .profile-photo { width: 42px; height: 42px; }
2911}
2912
2913/* Grid-tegels iets strakker gaten */
2914.grid-tiles { gap: 3px; }
2915
2916/* Post-cover margin */
2917.post-cover { margin: 0 0 1rem; }
2918
2919/* Audio player wat lichter */
2920#pcms-audio-bar { padding: .55rem 1rem; }
2921
2922/* v8.1 — pagination CTA + mobile tap target */
2923.pagination-cta {
2924 display: inline-block;
2925 font-family: var(--font-ui);
2926 font-size: .72rem;
2927 font-weight: 600;
2928 color: var(--accent);
2929 margin-top: .35rem;
2930 letter-spacing: .02em;
2931 opacity: .9;
2932}
2933a.pagination-item:hover .pagination-cta { opacity: 1; }
2934
2935/* Mobiel: nog meer tap-feedback + iets prominenter */
2936@media (max-width: 640px) {
2937 a.pagination-item {
2938 padding: 1.1rem 1rem;
2939 min-height: 5.5rem;
2940 border-width: 2px;
2941 }
2942 a.pagination-item:active {
2943 background: color-mix(in srgb, var(--accent) 10%, var(--paper-2));
2944 transform: scale(.98);
2945 }
2946 .pagination-title { font-size: 1rem; }
2947 .pagination-cta { font-size: .75rem; }
2948 .pagination .icon { width: 1.5em; height: 1.5em; }
2949}
2950
2951
2952
2953/* v8.3 / v9.4 — PWA install button (alleen zichtbaar als browser install ondersteunt) */
2954.nav-install-btn[hidden] { display: none; }
2955.nav-install-btn {
2956 position: relative;
2957 display: inline-flex;
2958 align-items: center;
2959 justify-content: center;
2960 gap: .35rem;
2961 background: linear-gradient(135deg,
2962 var(--accent),
2963 color-mix(in srgb, var(--accent) 80%, #000));
2964 color: #fff;
2965 border: none;
2966 border-radius: .65rem;
2967 padding: .45rem .85rem;
2968 font-size: .8rem;
2969 font-weight: 600;
2970 line-height: 1;
2971 cursor: pointer;
2972 overflow: hidden;
2973 isolation: isolate;
2974 box-shadow:
2975 0 1px 0 rgba(255,255,255,.15) inset,
2976 0 2px 6px color-mix(in srgb, var(--accent) 35%, transparent);
2977 transition:
2978 transform .15s cubic-bezier(.4, 0, .2, 1),
2979 box-shadow .2s ease,
2980 filter .15s ease;
2981}
2982.nav-install-btn::before {
2983 content: "";
2984 position: absolute;
2985 top: 0;
2986 left: -100%;
2987 width: 60%;
2988 height: 100%;
2989 background: linear-gradient(110deg,
2990 transparent 30%,
2991 rgba(255,255,255,.22) 50%,
2992 transparent 70%);
2993 z-index: -1;
2994 animation: pcmsInstallShimmer 4s ease-in-out infinite;
2995 pointer-events: none;
2996}
2997.nav-install-btn:hover {
2998 transform: translateY(-1px);
2999 filter: brightness(1.08);
3000 box-shadow:
3001 0 1px 0 rgba(255,255,255,.2) inset,
3002 0 4px 10px color-mix(in srgb, var(--accent) 50%, transparent);
3003}
3004.nav-install-btn:active { transform: translateY(0); }
3005.nav-install-btn .icon {
3006 flex-shrink: 0;
3007 transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
3008}
3009.nav-install-btn:hover .icon { transform: translateY(-1px); }
3010@media (prefers-reduced-motion: reduce) {
3011 .nav-install-btn::before { animation: none; left: -100%; }
3012 .nav-install-btn:hover { transform: none; }
3013 .nav-install-btn:hover .icon { transform: none; }
3014}
3015/* Als PWA al draait (standalone mode) — verberg install-prompt knop volledig */
3016@media all and (display-mode: standalone) {
3017 #pwa-install-btn { display: none !important; }
3018}
3019
3020/* ========== v8.9.9 — Privé-post indicators ========== */
3021.post-private-banner {
3022 display: flex;
3023 align-items: center;
3024 gap: .6rem;
3025 padding: .75rem 1rem;
3026 background: color-mix(in srgb, #eab308 12%, var(--paper, #fff));
3027 border: 1px solid color-mix(in srgb, #eab308 40%, transparent);
3028 border-radius: 8px;
3029 margin: 0 0 1rem;
3030 font-size: .88rem;
3031 color: var(--ink, #1a1a1a);
3032}
3033.post-private-banner strong {
3034 color: #b45309;
3035}
3036
3037.grid-tile-private {
3038 position: absolute;
3039 top: 8px;
3040 left: 8px;
3041 padding: 3px 8px;
3042 background: rgba(0,0,0,0.7);
3043 color: #fde68a;
3044 font-size: .7rem;
3045 font-weight: 700;
3046 border-radius: 999px;
3047 z-index: 3;
3048 backdrop-filter: blur(4px);
3049 -webkit-backdrop-filter: blur(4px);
3050}
3051
3052/* ========== v8.9.10 — Social chip (inline in post-body) ========== */
3053.social-chip {
3054 display: inline-flex;
3055 align-items: center;
3056 gap: .45rem;
3057 padding: .35rem .75rem;
3058 background: color-mix(in srgb, var(--accent) 10%, transparent);
3059 border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
3060 border-radius: 999px;
3061 color: var(--ink, #1a1a1a);
3062 text-decoration: none;
3063 font-family: var(--font-ui, system-ui);
3064 font-size: .85rem;
3065 font-weight: 600;
3066 line-height: 1.2;
3067 transition: all .15s;
3068 vertical-align: middle;
3069 margin: 0 .1rem;
3070}
3071.social-chip:hover {
3072 background: var(--accent);
3073 color: #fff;
3074 border-color: var(--accent);
3075 text-decoration: none;
3076 transform: translateY(-1px);
3077 box-shadow: 0 2px 8px color-mix(in srgb, var(--accent) 40%, transparent);
3078}
3079.social-chip .icon {
3080 width: 16px;
3081 height: 16px;
3082 flex-shrink: 0;
3083}
3084.social-chip-icon-only {
3085 width: 36px;
3086 height: 36px;
3087 padding: 0;
3088 justify-content: center;
3089 border-radius: 50%;
3090}
3091.social-chip-icon-only .icon {
3092 width: 18px;
3093 height: 18px;
3094}
3095
3096/* v8.9.34 — player hidden state + post audio blocks
3097 v9.3 — Hide-rules uitgeschakeld: mini-player blijft permanent zichtbaar
3098 zodat 'ie niet meer verdwijnt bij browser-back of navigatie. */
3099.audio-player.is-hidden {
3100 /* display: none !important; */
3101}
3102body:not(.has-audio-player) #pcms-audio-player.is-hidden {
3103 /* display: none !important; */
3104}
3105
3106/* Post audio track — single track row in een post */
3107/* Lokale audio-track — visueel consistent met .post-audio-external */
3108.post-audio-track {
3109 display: flex;
3110 align-items: center;
3111 gap: .75rem;
3112 padding: .65rem .85rem;
3113 background: var(--paper-2, color-mix(in srgb, var(--ink) 4%, transparent));
3114 border: 1px solid var(--rule, rgba(0,0,0,.08));
3115 border-radius: 10px;
3116 margin: .75rem 0;
3117 transition: background .15s, border-color .15s;
3118}
3119.post-audio-track:hover {
3120 border-color: var(--accent, #c2410c);
3121 background: color-mix(in srgb, var(--accent, #c2410c) 5%, var(--paper-2, transparent));
3122}
3123/* Korte highlight wanneer je via de mini-speler naar deze track springt. */
3124.post-audio-track.pat-flash,
3125.post-album-track-compact.pat-flash {
3126 animation: patFlash 1.6s ease-out;
3127 border-radius: 8px;
3128}
3129/* Blijvende highlight op de track die NU actief is in de speler. */
3130.post-audio-track.pat-playing,
3131.post-album-track-compact.pat-playing {
3132 background: color-mix(in srgb, var(--accent, #c2410c) 12%, var(--paper-2, transparent));
3133 box-shadow: inset 3px 0 0 0 var(--accent, #c2410c);
3134 border-radius: 8px;
3135}
3136@keyframes patFlash {
3137 0%, 30% { border-color: var(--accent, #c2410c); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, #c2410c) 35%, transparent); }
3138 100% { box-shadow: 0 0 0 0 transparent; }
3139}
3140.post-audio-track .pat-play {
3141 flex-shrink: 0;
3142 width: 42px;
3143 height: 42px;
3144 border-radius: 8px; /* zelfde rounded-square als pae-icon */
3145 border: none;
3146 background: var(--accent, #c2410c);
3147 color: var(--paper, #fff);
3148 cursor: pointer;
3149 display: inline-flex;
3150 align-items: center;
3151 justify-content: center;
3152 transition: transform .1s, background .15s;
3153 padding: 0;
3154 position: relative;
3155 overflow: hidden;
3156}
3157.post-audio-track .pat-play:hover { transform: scale(1.04); }
3158.post-audio-track .pat-play:active { transform: scale(.96); }
3159.post-audio-track .pat-play svg,
3160.post-audio-track .pat-play .pat-sitelogo {
3161 width: 100%; height: 100%;
3162 position: absolute;
3163 top: 0; left: 0;
3164 transition: opacity .15s;
3165}
3166.post-audio-track .pat-play .icon-play,
3167.post-audio-track .pat-play .icon-pause {
3168 width: 18px; height: 18px;
3169 position: absolute;
3170 top: 50%; left: 50%;
3171 transform: translate(-50%, -50%);
3172 fill: currentColor;
3173 opacity: 0; /* verborgen tot hover of is-current */
3174}
3175/* Site logo: object-cover binnen 42x42 box */
3176.post-audio-track .pat-play .pat-sitelogo {
3177 object-fit: cover;
3178 opacity: 1;
3179}
3180.post-audio-track .pat-play .pat-sitelogo-fallback {
3181 padding: 11px; /* SVG music-note iets kleiner in box */
3182 opacity: 1;
3183}
3184/* Bij hover: site logo faded, play-icoon verschijnt */
3185.post-audio-track:hover .pat-play .pat-sitelogo { opacity: 0.25; }
3186.post-audio-track:hover .pat-play .icon-play { opacity: 1; }
3187/* Bij current + playing: toon pause-icon */
3188.post-audio-track.is-current .pat-play .pat-sitelogo { opacity: 0.25; }
3189.post-audio-track.is-current .pat-play .icon-play { opacity: 1; }
3190.post-audio-track.is-current.is-playing .pat-play .icon-play { opacity: 0; }
3191.post-audio-track.is-current.is-playing .pat-play .icon-pause { opacity: 1; }
3192.post-audio-track.is-current {
3193 border-color: var(--accent, #c2410c);
3194 background: color-mix(in srgb, var(--accent, #c2410c) 10%, transparent);
3195}
3196.post-audio-track .pat-meta {
3197 flex: 1;
3198 min-width: 0;
3199 display: flex;
3200 flex-direction: column;
3201 gap: 2px;
3202}
3203.post-audio-track .pat-title {
3204 display: block;
3205 font-weight: 600;
3206 color: var(--ink);
3207 font-size: .95rem;
3208 overflow: hidden;
3209 text-overflow: ellipsis;
3210 white-space: nowrap;
3211}
3212.post-audio-track .pat-artist {
3213 display: block;
3214 font-size: .78rem;
3215 color: var(--ink-muted, var(--ink));
3216 opacity: .65;
3217 overflow: hidden;
3218 text-overflow: ellipsis;
3219 white-space: nowrap;
3220}
3221.post-audio-track .pat-duration {
3222 flex-shrink: 0;
3223 font-family: ui-monospace, monospace;
3224 font-size: .8rem;
3225 opacity: .55;
3226}
3227
3228/* Album block in een post */
3229.post-album {
3230 position: relative;
3231 border: 1px solid var(--rule, rgba(0,0,0,.1));
3232 border-radius: 14px;
3233 overflow: hidden;
3234 margin: 1.25rem 0;
3235 background: var(--paper-2, color-mix(in srgb, var(--ink) 3%, transparent));
3236}
3237.post-album-header {
3238 display: flex;
3239 gap: .75rem;
3240 padding: .55rem .7rem;
3241 align-items: center;
3242}
3243.post-album-cover {
3244 width: 120px;
3245 height: 120px;
3246 border-radius: 8px;
3247 background-size: cover;
3248 background-position: center;
3249 background-color: var(--rule);
3250 flex-shrink: 0;
3251}
3252/* v9.0 — Collage van track-covers als album-cover leeg is */
3253.post-album-cover-collage {
3254 display: grid;
3255 grid-template-columns: 1fr 1fr;
3256 grid-template-rows: 1fr 1fr;
3257 gap: 0;
3258 overflow: hidden;
3259 background: transparent;
3260}
3261.post-album-cover-collage .post-album-cover-tile {
3262 background-size: cover;
3263 background-position: center;
3264 width: 100%;
3265 height: 100%;
3266}
3267/* Empty state: gradient met muziek-noot */
3268.post-album-cover-empty {
3269 display: flex;
3270 align-items: center;
3271 justify-content: center;
3272 background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 25%, var(--paper-2)), color-mix(in srgb, var(--accent) 10%, var(--paper)));
3273 color: var(--accent, #c2410c);
3274}
3275.post-album-cover-empty svg {
3276 width: 42%;
3277 height: 42%;
3278 opacity: .55;
3279}
3280.post-album-info {
3281 flex: 1;
3282 min-width: 0;
3283}
3284.post-album-label {
3285 text-transform: uppercase;
3286 font-size: .68rem;
3287 letter-spacing: .1em;
3288 opacity: .55;
3289 margin: 0 0 .15rem;
3290 font-weight: 700;
3291}
3292.post-album-title {
3293 font-family: var(--font-display);
3294 font-size: 1.1rem;
3295 font-weight: 600;
3296 margin: 0 0 .1rem;
3297 line-height: 1.15;
3298 letter-spacing: -0.01em;
3299}
3300.post-album-artist {
3301 font-size: .88rem;
3302 opacity: .8;
3303 margin: 0 0 .12rem;
3304 line-height: 1.25;
3305}
3306.post-album-meta {
3307 font-size: .74rem;
3308 opacity: .55;
3309 margin: 0;
3310 line-height: 1.2;
3311}
3312.post-album-playall {
3313 margin-top: .75rem;
3314 padding: .45rem .9rem;
3315 background: var(--accent, #c2410c);
3316 color: var(--paper, #fff);
3317 border: none;
3318 border-radius: 6px;
3319 font-weight: 600;
3320 cursor: pointer;
3321 font-size: .88rem;
3322 display: inline-flex;
3323 align-items: center;
3324 gap: .35rem;
3325}
3326.post-album-playall:hover { filter: brightness(1.08); }
3327
3328/* ============================================================
3329 v9.0 — Album cover clickable button
3330 ============================================================ */
3331.post-album-cover-btn {
3332 position: relative;
3333 background: none;
3334 border: none;
3335 padding: 0;
3336 margin: 0;
3337 cursor: pointer;
3338 flex-shrink: 0;
3339 border-radius: 8px;
3340 overflow: hidden;
3341 display: block;
3342 width: auto;
3343 /* v9.1 — voorkom mobile 300ms double-tap zoom delay, anders zou 2× snel klikken
3344 een zoom triggeren i.p.v. 2× click-events */
3345 touch-action: manipulation;
3346 -webkit-tap-highlight-color: transparent;
3347}
3348.post-album-cover-btn .post-album-cover {
3349 display: block;
3350 width: 76px;
3351 height: 76px;
3352 border-radius: 7px;
3353 background-size: cover;
3354 background-position: center;
3355 background-color: var(--rule);
3356 transition: transform .25s ease;
3357}
3358.post-album-cover-btn:hover .post-album-cover {
3359 transform: scale(1.04);
3360}
3361.post-album-cover-btn .post-album-cover-empty {
3362 background: linear-gradient(135deg,
3363 color-mix(in srgb, var(--accent, #c2410c) 35%, var(--paper)),
3364 color-mix(in srgb, var(--accent, #c2410c) 10%, var(--paper-2)));
3365 display: flex;
3366 align-items: center;
3367 justify-content: center;
3368}
3369.post-album-cover-btn .post-album-cover-empty svg {
3370 width: 28px;
3371 height: 28px;
3372 color: color-mix(in srgb, var(--accent, #c2410c) 60%, transparent);
3373}
3374/* Play overlay op hover */
3375.post-album-cover-play {
3376 position: absolute;
3377 inset: 0;
3378 display: flex;
3379 align-items: center;
3380 justify-content: center;
3381 background: rgba(0, 0, 0, .35);
3382 opacity: 0;
3383 transition: opacity .2s ease;
3384 border-radius: 8px;
3385 pointer-events: none;
3386}
3387.post-album-cover-play svg {
3388 width: 48px;
3389 height: 48px;
3390 color: #fff;
3391 filter: drop-shadow(0 2px 8px rgba(0,0,0,.4));
3392}
3393.post-album-cover-btn:hover .post-album-cover-play,
3394.post-album-cover-btn:focus-visible .post-album-cover-play {
3395 opacity: 1;
3396}
3397
3398/* ============================================================
3399 v1 P52 — Admin actions overlay (edit / delete)
3400 Only rendered when the viewer has god role. Sits top-right
3401 of the card so it doesn't compete with the cover play affordance.
3402 ============================================================ */
3403.post-album-actions {
3404 position: absolute;
3405 top: .4rem;
3406 right: .4rem;
3407 display: flex;
3408 gap: .25rem;
3409 z-index: 2;
3410}
3411.post-album-action {
3412 width: 28px;
3413 height: 28px;
3414 border-radius: 6px;
3415 border: 1px solid var(--rule);
3416 background: color-mix(in srgb, var(--paper) 78%, transparent);
3417 backdrop-filter: blur(8px);
3418 -webkit-backdrop-filter: blur(8px);
3419 color: var(--ink);
3420 display: inline-flex;
3421 align-items: center;
3422 justify-content: center;
3423 cursor: pointer;
3424 text-decoration: none;
3425 opacity: .65;
3426 padding: 0;
3427 transition: opacity .15s ease, transform .15s ease, background .15s ease, color .15s ease, border-color .15s ease;
3428 -webkit-tap-highlight-color: transparent;
3429}
3430.post-album-action:hover,
3431.post-album-action:focus-visible {
3432 opacity: 1;
3433 transform: translateY(-1px);
3434 outline: none;
3435}
3436.post-album-action.is-danger:hover,
3437.post-album-action.is-danger:focus-visible {
3438 background: color-mix(in srgb, #c2410c 18%, var(--paper));
3439 border-color: color-mix(in srgb, #c2410c 45%, var(--rule));
3440 color: #c2410c;
3441}
3442.post-album-action svg {
3443 width: 15px;
3444 height: 15px;
3445 display: block;
3446}
3447
3448/* ============================================================
3449 v9.0 — Compacte tracklist (informatief, niet-klikbaar)
3450 ============================================================ */
3451.post-album-tracks {
3452 list-style: none;
3453 padding: 0;
3454 margin: 0;
3455 border-top: 1px solid var(--rule);
3456}
3457/* v9.4 — Playlist insert modal rows */
3458.pli-row {
3459 display: flex;
3460 align-items: center;
3461 gap: .75rem;
3462 padding: .65rem .5rem;
3463 border-bottom: 1px solid var(--border);
3464}
3465.pli-row:last-child { border-bottom: none; }
3466.pli-row-cover {
3467 width: 44px;
3468 height: 44px;
3469 border-radius: 6px;
3470 background-size: cover;
3471 background-position: center;
3472 background-color: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3473 flex-shrink: 0;
3474 display: flex;
3475 align-items: center;
3476 justify-content: center;
3477 font-size: 1.4rem;
3478}
3479.pli-row-info {
3480 flex: 1;
3481 min-width: 0;
3482}
3483.pli-row-title {
3484 font-weight: 600;
3485 overflow: hidden;
3486 text-overflow: ellipsis;
3487 white-space: nowrap;
3488}
3489.pli-row-meta {
3490 font-size: .82rem;
3491 overflow: hidden;
3492 text-overflow: ellipsis;
3493 white-space: nowrap;
3494}
3495.post-playlist-placeholder {
3496 margin: 1rem 0;
3497 user-select: none;
3498}
3499
3500/* v9.4 — Generic modal classes (gebruikt door playlist-editor en andere modals) */
3501.pcms-modal-backdrop {
3502 position: fixed;
3503 inset: 0;
3504 background: rgba(0, 0, 0, .6);
3505 display: flex;
3506 align-items: center;
3507 justify-content: center;
3508 z-index: 9000;
3509 padding: 1rem;
3510 box-sizing: border-box;
3511 overflow-y: auto;
3512}
3513.pcms-modal {
3514 background: var(--paper, #fff);
3515 color: var(--ink, #000);
3516 border-radius: 12px;
3517 width: 100%;
3518 max-width: 640px;
3519 max-height: calc(100vh - 2rem);
3520 display: flex;
3521 flex-direction: column;
3522 overflow: hidden;
3523 box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
3524}
3525.pcms-modal-header {
3526 display: flex;
3527 align-items: center;
3528 justify-content: space-between;
3529 padding: 1rem 1.25rem;
3530 border-bottom: 1px solid var(--border);
3531 flex-shrink: 0;
3532}
3533.pcms-modal-header h3 { font-size: 1.1rem; }
3534.pcms-modal-close {
3535 background: transparent;
3536 border: none;
3537 font-size: 1.6rem;
3538 line-height: 1;
3539 cursor: pointer;
3540 padding: .25rem .5rem;
3541 color: var(--fg-muted, #666);
3542 border-radius: 4px;
3543}
3544.pcms-modal-close:hover {
3545 background: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3546}
3547.pcms-modal-body {
3548 padding: 1.25rem;
3549 overflow-y: auto;
3550 overscroll-behavior: contain;
3551 flex: 1;
3552 min-height: 0;
3553}
3554.pcms-modal-footer {
3555 display: flex;
3556 gap: .5rem;
3557 justify-content: flex-end;
3558 padding: .75rem 1.25rem;
3559 border-top: 1px solid var(--border);
3560 flex-shrink: 0;
3561 background: color-mix(in srgb, var(--ink, #000) 3%, transparent);
3562}
3563
3564/* On mobile: full-screen modal */
3565@media (max-width: 600px) {
3566 .pcms-modal-backdrop {
3567 padding: 0;
3568 }
3569 .pcms-modal {
3570 border-radius: 0;
3571 max-width: 100%;
3572 max-height: 100vh;
3573 height: 100vh;
3574 }
3575}
3576
3577/* v9.4 — Media → Playlists tab */
3578.playlists-page-header {
3579 display: flex;
3580 flex-wrap: wrap;
3581 gap: 1rem;
3582 align-items: center;
3583 justify-content: space-between;
3584 margin-bottom: 1.25rem;
3585}
3586.playlists-page-header > p { flex: 1; min-width: 200px; }
3587.playlists-grid {
3588 display: grid;
3589 grid-template-columns: 1fr;
3590 gap: .75rem;
3591}
3592@media (min-width: 720px) {
3593 .playlists-grid { grid-template-columns: repeat(2, 1fr); }
3594}
3595@media (min-width: 1100px) {
3596 .playlists-grid { grid-template-columns: repeat(3, 1fr); }
3597}
3598.playlist-card {
3599 display: grid;
3600 grid-template-columns: 64px 1fr auto;
3601 gap: .75rem;
3602 align-items: center;
3603 padding: .75rem;
3604 border: 1px solid var(--border);
3605 border-radius: var(--radius);
3606 background: var(--paper, #fff);
3607}
3608.playlist-card-cover {
3609 width: 64px;
3610 height: 64px;
3611 border-radius: 8px;
3612 overflow: hidden;
3613 background-color: color-mix(in srgb, var(--ink, #000) 6%, transparent);
3614 display: flex;
3615 align-items: center;
3616 justify-content: center;
3617}
3618.playlist-card-cover img {
3619 width: 100%;
3620 height: 100%;
3621 object-fit: cover;
3622}
3623.playlist-card-cover-empty { font-size: 1.6rem; opacity: .5; }
3624.playlist-card-info { min-width: 0; }
3625.playlist-card-title {
3626 font-weight: 600;
3627 overflow: hidden;
3628 text-overflow: ellipsis;
3629 white-space: nowrap;
3630}
3631.playlist-card-artist,
3632.playlist-card-meta {
3633 font-size: .82rem;
3634 overflow: hidden;
3635 text-overflow: ellipsis;
3636 white-space: nowrap;
3637}
3638.playlist-card-actions {
3639 display: flex;
3640 gap: .25rem;
3641 flex-shrink: 0;
3642}
3643
3644/* v9.4 — Playlist editor modal (mobile-friendly, single-column) */
3645.pl-editor {
3646 /* Erft van .pcms-modal */
3647}
3648.pl-editor-meta {
3649 display: grid;
3650 grid-template-columns: 1fr;
3651 gap: .75rem;
3652 margin-bottom: 1rem;
3653}
3654@media (min-width: 560px) {
3655 .pl-editor-meta {
3656 grid-template-columns: 1fr 1fr;
3657 }
3658 .pl-editor-meta .pl-editor-field-full { grid-column: 1 / -1; }
3659}
3660.pl-editor-field {
3661 display: flex;
3662 flex-direction: column;
3663 gap: .25rem;
3664 min-width: 0;
3665}
3666.pl-editor-field span {
3667 font-size: .82rem;
3668 color: var(--fg-muted, #666);
3669 font-weight: 500;
3670}
3671.pl-editor-field input,
3672.pl-editor-field select {
3673 width: 100%;
3674 box-sizing: border-box;
3675 padding: .5rem .65rem;
3676 font-size: .95rem;
3677 border: 1px solid var(--border);
3678 border-radius: 6px;
3679 background: var(--paper, #fff);
3680 color: var(--ink, #000);
3681}
3682.pl-editor-field input:focus,
3683.pl-editor-field select:focus {
3684 outline: 2px solid var(--accent, #5a8a5a);
3685 outline-offset: -1px;
3686}
3687.pl-editor-section-title {
3688 margin: 1.25rem 0 .5rem;
3689 font-size: 1rem;
3690 font-weight: 600;
3691}
3692.pl-tracks-selected {
3693 border: 1px solid var(--border);
3694 border-radius: var(--radius);
3695 background: var(--paper, #fff);
3696 min-height: 60px;
3697 margin-bottom: 1rem;
3698 padding: .25rem;
3699}
3700.pl-tracks-empty {
3701 padding: 1.5rem;
3702 text-align: center;
3703 color: var(--fg-muted, #666);
3704 font-size: .9rem;
3705}
3706.pl-track-row {
3707 display: grid;
3708 grid-template-columns: 32px 36px 1fr auto;
3709 gap: .5rem;
3710 align-items: center;
3711 padding: .5rem;
3712 border-bottom: 1px solid var(--border);
3713 background: var(--paper, #fff);
3714 user-select: none;
3715 touch-action: pan-x;
3716}
3717.pl-track-row:last-child { border-bottom: none; }
3718.pl-track-row.is-dragging {
3719 opacity: .55;
3720 transform: scale(.98);
3721 background: color-mix(in srgb, var(--accent, #5a8a5a) 10%, transparent);
3722 border-radius: 6px;
3723}
3724.pl-track-row.drop-target-above {
3725 box-shadow: inset 0 2px 0 0 var(--accent, #5a8a5a);
3726}
3727.pl-track-row.drop-target-below {
3728 box-shadow: inset 0 -2px 0 0 var(--accent, #5a8a5a);
3729}
3730.pl-track-handle {
3731 cursor: grab;
3732 font-size: 1.2rem;
3733 line-height: 1;
3734 color: var(--fg-muted, #666);
3735 display: flex;
3736 align-items: center;
3737 justify-content: center;
3738 height: 32px;
3739 width: 32px;
3740 border-radius: 4px;
3741 flex-shrink: 0;
3742}
3743.pl-track-handle:active { cursor: grabbing; }
3744.pl-track-handle:hover {
3745 background: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3746}
3747.pl-track-num {
3748 text-align: center;
3749 color: var(--fg-muted, #666);
3750 font-size: .85rem;
3751 width: 36px;
3752}
3753.pl-track-info {
3754 min-width: 0;
3755 overflow: hidden;
3756}
3757.pl-track-title {
3758 font-weight: 500;
3759 overflow: hidden;
3760 text-overflow: ellipsis;
3761 white-space: nowrap;
3762}
3763.pl-track-artist {
3764 font-size: .78rem;
3765 color: var(--fg-muted, #666);
3766 overflow: hidden;
3767 text-overflow: ellipsis;
3768 white-space: nowrap;
3769}
3770.pl-track-remove {
3771 background: transparent;
3772 border: none;
3773 cursor: pointer;
3774 padding: .35rem;
3775 border-radius: 4px;
3776 color: var(--fg-muted, #666);
3777 font-size: 1.2rem;
3778 line-height: 1;
3779}
3780.pl-track-remove:hover {
3781 background: color-mix(in srgb, #c00 12%, transparent);
3782 color: #c00;
3783}
3784
3785/* Available tracks panel */
3786.pl-tracks-available-panel {
3787 border: 1px solid var(--border);
3788 border-radius: var(--radius);
3789 background: var(--paper, #fff);
3790}
3791.pl-tracks-available-search {
3792 padding: .5rem;
3793 border-bottom: 1px solid var(--border);
3794}
3795.pl-tracks-available-search input {
3796 width: 100%;
3797 box-sizing: border-box;
3798}
3799.pl-tracks-available-list {
3800 max-height: 30vh;
3801 overflow-y: auto;
3802}
3803.pl-track-row-available {
3804 display: grid;
3805 grid-template-columns: 1fr auto;
3806 gap: .5rem;
3807 align-items: center;
3808 padding: .5rem;
3809 border-bottom: 1px solid var(--border);
3810 cursor: pointer;
3811}
3812.pl-track-row-available:last-child { border-bottom: none; }
3813.pl-track-row-available:hover {
3814 background: color-mix(in srgb, var(--accent, #5a8a5a) 8%, transparent);
3815}
3816.pl-track-row-available.is-already-added {
3817 opacity: .4;
3818 pointer-events: none;
3819}
3820.pl-track-add-btn {
3821 background: transparent;
3822 border: 1px solid var(--border);
3823 border-radius: 4px;
3824 padding: .25rem .5rem;
3825 cursor: pointer;
3826 font-size: .85rem;
3827 color: var(--accent, #5a8a5a);
3828}
3829
3830/* v9.3 — Tracklist items zijn nu klikbare <button class="pat-row"> binnen <li>.
3831 De LI is puur een container zonder visuele styling; alles gebeurt op de button. */
3832.post-album-track-compact {
3833 padding: 0;
3834 margin: 0;
3835 border-bottom: 1px solid var(--rule);
3836 list-style: none;
3837}
3838.post-album-track-compact:last-child { border-bottom: none; }
3839
3840.pat-row {
3841 display: grid;
3842 grid-template-columns: 32px 1fr auto;
3843 gap: .65rem;
3844 align-items: center;
3845 width: 100%;
3846 padding: .5rem .85rem;
3847 background: transparent;
3848 border: none;
3849 color: inherit;
3850 font: inherit;
3851 font-size: .82rem;
3852 text-align: left;
3853 cursor: pointer;
3854 position: relative;
3855 transition: background .15s ease;
3856}
3857.pat-row:hover {
3858 background: color-mix(in srgb, var(--ink, #000) 6%, transparent);
3859}
3860.pat-row:active { transform: scale(.995); }
3861[data-theme="dark"] .pat-row:hover {
3862 background: color-mix(in srgb, var(--paper, #fff) 10%, transparent);
3863}
3864
3865/* Leader: track-nummer OF cover-thumb (afhankelijk van kind).
3866 v9.3 — pat-leader is altijd 32×32, met overgang voor spinner-vervanging. */
3867.pat-row .pat-num,
3868.pat-row .pat-cover {
3869 width: 32px;
3870 height: 32px;
3871 border-radius: 4px;
3872 flex-shrink: 0;
3873 transition: opacity .25s ease, transform .25s ease;
3874}
3875.pat-row .pat-num {
3876 font-family: ui-monospace, monospace;
3877 font-size: .8rem;
3878 opacity: .5;
3879 display: flex;
3880 align-items: center;
3881 justify-content: center;
3882}
3883.pat-row .pat-cover {
3884 background-size: cover;
3885 background-position: center;
3886 background-color: color-mix(in srgb, var(--ink, #000) 8%, transparent);
3887}
3888
3889/* v9.3 — Loading-spiraal als overlay op de leader-kolom.
3890 pat-num/pat-cover faden uit, spinner faded in via ::before. */
3891.pat-row::before {
3892 content: "";
3893 position: absolute;
3894 left: .85rem; top: 50%;
3895 width: 32px; height: 32px;
3896 transform: translateY(-50%);
3897 color: var(--accent, #c2410c);
3898 background-color: currentColor;
3899 -webkit-mask: url('/assets/spinner.svg') center/26px 26px no-repeat;
3900 mask: url('/assets/spinner.svg') center/26px 26px no-repeat;
3901 opacity: 0;
3902 transition: opacity .25s ease;
3903 pointer-events: none;
3904 animation: pat-spinner-rotate 1.2s linear infinite;
3905 animation-play-state: paused;
3906}
3907.pat-row.is-loading::before {
3908 opacity: 1;
3909 animation-play-state: running;
3910}
3911.pat-row.is-loading .pat-num,
3912.pat-row.is-loading .pat-cover {
3913 opacity: 0;
3914 transform: scale(.85);
3915}
3916@keyframes pat-spinner-rotate {
3917 from { transform: translateY(-50%) rotate(0deg); }
3918 to { transform: translateY(-50%) rotate(-360deg); }
3919}
3920
3921/* Meta-kolom */
3922.pat-row .pat-meta {
3923 display: flex;
3924 flex-direction: column;
3925 min-width: 0;
3926 gap: 1px;
3927 overflow: hidden;
3928}
3929.pat-row .pat-title {
3930 font-weight: 500;
3931 overflow: hidden;
3932 text-overflow: ellipsis;
3933 white-space: nowrap;
3934}
3935.pat-row .pat-artist {
3936 font-size: .72rem;
3937 opacity: .6;
3938 overflow: hidden;
3939 text-overflow: ellipsis;
3940 white-space: nowrap;
3941}
3942.pat-row .pat-duration {
3943 font-family: ui-monospace, monospace;
3944 font-size: .72rem;
3945 opacity: .55;
3946 font-variant-numeric: tabular-nums;
3947 white-space: nowrap;
3948}
3949.pat-row .pat-duration-empty {
3950 opacity: .25;
3951}
3952
3953/* is-current — actieve track in de player */
3954.pat-row.is-current {
3955 background: color-mix(in srgb, var(--accent, #c2410c) 12%, transparent);
3956}
3957.pat-row.is-current .pat-title,
3958.pat-row.is-current .pat-artist { color: var(--accent, #c2410c); }
3959
3960/* v9.3 — Marquee bij actief afspelen: titel scrollt heen-en-weer.
3961 --pat-shift wordt door JS gezet (= overflow in pixels). Bij 0 → geen
3962 beweging want translateX(0) blijft 0.
3963 Snelle cyclus (6s) met korte rust aan beide uiteinden (8%) zodat 't
3964 vlot voelt zonder onleesbaar te zijn. */
3965.pat-row.is-current.is-playing .pat-title {
3966 animation: pat-title-marquee 6s ease-in-out infinite alternate;
3967 text-overflow: clip;
3968 overflow: visible;
3969 will-change: transform;
3970}
3971@keyframes pat-title-marquee {
3972 0%, 8% { transform: translateX(0); }
3973 92%, 100% { transform: translateX(calc(-1 * var(--pat-shift, 0px))); }
3974}
3975
3976/* ============================================================
3977 v9.0 — CSS-migratie voor OUDE opgeslagen albums
3978 Oude posts hebben <li class="post-audio-track"> met play-knoppen + cover-spans.
3979 We renderen die VISUEEL als compact, zonder de HTML aan te passen.
3980 ============================================================ */
3981.post-album-tracks .post-audio-track {
3982 display: grid;
3983 grid-template-columns: 28px 1fr auto;
3984 gap: .75rem;
3985 align-items: center;
3986 padding: .5rem .85rem;
3987 margin: 0;
3988 border: none;
3989 border-bottom: 1px solid var(--rule);
3990 background: transparent;
3991 border-radius: 0;
3992 cursor: default;
3993 font-size: .92rem;
3994}
3995.post-album-tracks .post-audio-track:last-child { border-bottom: none; }
3996/* Verberg de cover-thumb en play-button in OUDE saved posts */
3997.post-album-tracks .post-audio-track .pat-cover,
3998.post-album-tracks .post-audio-track .pat-play {
3999 display: none !important;
4000}
4001.post-album-tracks .post-audio-track .pat-num {
4002 font-family: ui-monospace, monospace;
4003 font-size: .8rem;
4004 opacity: .45;
4005 text-align: center;
4006 width: auto;
4007}
4008.post-album-tracks .post-audio-track .pat-meta {
4009 display: flex;
4010 flex-direction: column;
4011 min-width: 0;
4012 gap: 1px;
4013}
4014.post-album-tracks .post-audio-track .pat-title {
4015 font-weight: 500;
4016 overflow: hidden;
4017 text-overflow: ellipsis;
4018 white-space: nowrap;
4019}
4020.post-album-tracks .post-audio-track .pat-artist {
4021 font-size: .78rem;
4022 opacity: .6;
4023}
4024.post-album-tracks .post-audio-track .pat-duration {
4025 font-family: ui-monospace, monospace;
4026 font-size: .78rem;
4027 opacity: .55;
4028}
4029.post-album-tracks .post-audio-track.is-current {
4030 background: color-mix(in srgb, var(--accent, #c2410c) 10%, transparent);
4031}
4032.post-album-tracks .post-audio-track.is-current .pat-num,
4033.post-album-tracks .post-audio-track.is-current .pat-title {
4034 color: var(--accent);
4035}
4036
4037@media (max-width: 540px) {
4038 .post-album-header { flex-direction: column; }
4039 .post-album-cover-btn .post-album-cover { width: 100%; max-width: 240px; height: auto; aspect-ratio: 1/1; }
4040}
4041@media (max-width: 380px) {
4042 .post-album-header { padding: .75rem; gap: .75rem; }
4043 .post-album-cover-btn .post-album-cover { max-width: 180px; }
4044 .post-album-title { font-size: 1.15rem; }
4045 .post-album-meta { font-size: .8rem; }
4046 .post-album-track-compact,
4047 .post-album-tracks .post-audio-track {
4048 grid-template-columns: 24px 1fr auto;
4049 gap: .5rem;
4050 padding: .4rem .6rem;
4051 font-size: .85rem;
4052 }
4053 .post-album-track-compact .pat-duration,
4054 .post-album-tracks .post-audio-track .pat-duration {
4055 font-size: .72rem;
4056 }
4057 /* Queue items in expand-sheet */
4058 .audio-sheet-queue-item { padding: .4rem .45rem; gap: .55rem; }
4059 .audio-sheet-queue-cover { width: 32px; height: 32px; }
4060 .audio-sheet-queue-title { font-size: .85rem; }
4061 .audio-sheet-queue-artist { font-size: .7rem; }
4062}
4063
4064/* External track (SoundCloud / YouTube / Spotify / etc) — klikbaar maar link-naar-platform */
4065.post-audio-external {
4066 display: flex;
4067 align-items: center;
4068 gap: .75rem;
4069 padding: .65rem .85rem;
4070 background: var(--paper-2, color-mix(in srgb, var(--ink) 4%, transparent));
4071 border: 1px solid var(--rule, rgba(0,0,0,.08));
4072 border-radius: 10px;
4073 margin: .75rem 0;
4074 text-decoration: none;
4075 color: var(--ink);
4076 transition: background .15s, border-color .15s;
4077}
4078.post-audio-external:hover {
4079 border-color: var(--accent);
4080 background: color-mix(in srgb, var(--accent) 5%, var(--paper-2, transparent));
4081}
4082.post-audio-external .pae-icon {
4083 flex-shrink: 0;
4084 width: 42px;
4085 height: 42px;
4086 border-radius: 8px;
4087 display: inline-flex;
4088 align-items: center;
4089 justify-content: center;
4090 background: var(--platform-color, #555);
4091 color: #fff;
4092 font-size: 1.2rem;
4093}
4094.post-audio-external .pae-icon-svg svg {
4095 width: 60%;
4096 height: 60%;
4097 fill: currentColor;
4098}
4099/* Per-platform vult de box net wat anders — brand-specifiek geoptimaliseerd */
4100.post-audio-external[data-platform="soundcloud"] .pae-icon-svg svg { width: 72%; height: auto; }
4101.post-audio-external[data-platform="spotify"] .pae-icon-svg svg { width: 72%; height: 72%; }
4102.post-audio-external[data-platform="youtube"] .pae-icon-svg svg { width: 68%; height: auto; }
4103.post-audio-external[data-platform="bandcamp"] .pae-icon-svg svg { width: 62%; height: auto; }
4104.post-audio-external[data-platform="apple"] .pae-icon-svg svg { width: 58%; height: 58%; }
4105.post-audio-external[data-platform="tidal"] .pae-icon-svg svg { width: 68%; height: auto; }
4106.post-audio-external[data-platform="deezer"] .pae-icon-svg svg { width: 65%; height: auto; }
4107.post-audio-external[data-platform="mixcloud"] .pae-icon-svg svg { width: 75%; height: auto; }
4108.post-audio-external[data-platform="soundcloud"] .pae-icon { background: #ff5500; }
4109.post-audio-external[data-platform="spotify"] .pae-icon { background: #1db954; }
4110.post-audio-external[data-platform="youtube"] .pae-icon { background: #ff0000; }
4111.post-audio-external[data-platform="bandcamp"] .pae-icon { background: #1da0c3; }
4112.post-audio-external[data-platform="apple"] .pae-icon { background: #fa243c; }
4113.post-audio-external[data-platform="tidal"] .pae-icon { background: #000; }
4114.post-audio-external[data-platform="deezer"] .pae-icon { background: #a238ff; }
4115.post-audio-external[data-platform="mixcloud"] .pae-icon { background: #314359; }
4116.post-audio-external[data-platform="other"] .pae-icon { background: #555; }
4117.post-audio-external .pae-meta {
4118 flex: 1;
4119 min-width: 0;
4120 display: flex;
4121 flex-direction: column;
4122 gap: 2px;
4123}
4124.post-audio-external .pae-title {
4125 display: block;
4126 font-weight: 600;
4127 overflow: hidden;
4128 text-overflow: ellipsis;
4129 white-space: nowrap;
4130 color: var(--ink);
4131}
4132.post-audio-external .pae-platform {
4133 display: block;
4134 font-size: .78rem;
4135 opacity: .65;
4136 text-transform: capitalize;
4137}
4138.post-audio-external .pae-go {
4139 flex-shrink: 0;
4140 opacity: .5;
4141 font-size: 1.1rem;
4142}
4143
4144/* =========================================================================
4145 v9.0 — Video player (inline)
4146 ========================================================================= */
4147
4148.post-video-figure {
4149 margin: 1.25rem 0;
4150 max-width: 100%;
4151}
4152
4153.post-video {
4154 display: block;
4155 width: 100%;
4156 max-width: 100%;
4157 height: auto;
4158 border-radius: 10px;
4159 background: #000;
4160 box-shadow: 0 4px 20px rgba(0,0,0,.15);
4161}
4162
4163.post-video-caption {
4164 margin-top: .5rem;
4165 font-size: .88rem;
4166 color: var(--ink-muted, color-mix(in srgb, var(--ink) 60%, transparent));
4167 text-align: center;
4168 line-height: 1.5;
4169}
4170
4171.post-video-caption strong {
4172 display: inline;
4173 font-weight: 600;
4174 color: var(--ink);
4175}
4176
4177@media (max-width: 640px) {
4178 .post-video-figure { margin: .75rem -.5rem; }
4179 .post-video { border-radius: 6px; }
4180}
4181
4182/* v9.3 — Floating "Bewerken" knop voor album-blokken in de post-editor.
4183 Verschijnt bij hover over een .post-album binnen #visual en wordt via JS
4184 geplaatst op de rechterbovenhoek van het blok. Niet in de opgeslagen HTML. */
4185.pcms-album-edit-overlay {
4186 position: absolute;
4187 z-index: 1000;
4188 transform: translateX(-100%);
4189 display: inline-flex;
4190 align-items: center;
4191 gap: .35rem;
4192 padding: .35rem .7rem;
4193 background: var(--accent, #c2410c);
4194 color: #fff;
4195 border: none;
4196 border-radius: 6px;
4197 font-size: .82rem;
4198 font-weight: 600;
4199 cursor: pointer;
4200 box-shadow: 0 4px 12px rgba(0, 0, 0, .18);
4201 transition: transform .12s ease, box-shadow .12s ease;
4202}
4203.pcms-album-edit-overlay:hover {
4204 transform: translateX(-100%) translateY(-1px);
4205 box-shadow: 0 6px 16px rgba(0, 0, 0, .24);
4206}
4207.pcms-album-edit-overlay:active {
4208 transform: translateX(-100%) translateY(0);
4209 box-shadow: 0 2px 6px rgba(0, 0, 0, .18);
4210}
4211
4212/* v9.3 — Drag-and-drop in de album-builder selected-lijst */
4213.ab-selected-row { cursor: default; }
4214.ab-selected-row .ab-drag-handle {
4215 display: inline-flex;
4216 align-items: center;
4217 justify-content: center;
4218 width: 18px;
4219 height: 100%;
4220 color: color-mix(in srgb, currentColor 40%, transparent);
4221 cursor: grab;
4222 user-select: none;
4223 font-size: .9rem;
4224 letter-spacing: -2px;
4225 flex-shrink: 0;
4226}
4227.ab-selected-row:hover .ab-drag-handle {
4228 color: color-mix(in srgb, currentColor 70%, transparent);
4229}
4230.ab-selected-row.is-dragging {
4231 opacity: .35;
4232 cursor: grabbing;
4233}
4234.ab-selected-row.is-dragging .ab-drag-handle { cursor: grabbing; }
4235/* Drop-indicator lijnen boven/onder de target rij */
4236.ab-selected-row.is-drag-target-before {
4237 box-shadow: 0 -2px 0 0 var(--accent, #c2410c) inset, 0 2px 0 0 var(--accent, #c2410c);
4238 /* Gebruik outline voor cross-browser zichtbaarheid */
4239 position: relative;
4240}
4241.ab-selected-row.is-drag-target-before::before {
4242 content: "";
4243 position: absolute;
4244 top: -1px; left: 0; right: 0;
4245 height: 2px;
4246 background: var(--accent, #c2410c);
4247 pointer-events: none;
4248}
4249.ab-selected-row.is-drag-target-after::after {
4250 content: "";
4251 position: absolute;
4252 bottom: -1px; left: 0; right: 0;
4253 height: 2px;
4254 background: var(--accent, #c2410c);
4255 pointer-events: none;
4256}
4257.ab-selected-row.is-drag-target-after { position: relative; }
4258
4259/* v9.3 — Playlist fallback states (missing of empty playlist reference in post) */
4260.post-playlist-missing, .post-playlist-empty {
4261 padding: 1rem;
4262 margin: .75rem 0;
4263 background: color-mix(in srgb, var(--accent, #c2410c) 8%, transparent);
4264 border: 1px dashed color-mix(in srgb, var(--accent, #c2410c) 30%, transparent);
4265 border-radius: 8px;
4266 font-size: .9rem;
4267}
4268.post-playlist-missing em, .post-playlist-empty em {
4269 opacity: .8;
4270}
4271
4272/* v9.3 — Install-app footer-knop */
4273.site-footer-install {
4274 display: flex;
4275 justify-content: center;
4276 padding: 1rem 1rem 1.25rem;
4277 border-top: 1px solid color-mix(in srgb, currentColor 8%, transparent);
4278 margin-top: .5rem;
4279}
4280
4281/* v9.4 — Cooler install-knop: gradient + shimmer + perfect centering.
4282 Twee kleur-stops voor diepte, animated shimmer-streep om aandacht te trekken,
4283 icon perfect verticaal gecentreerd via flex (was: net iets te hoog tov tekst). */
4284.install-app-btn {
4285 position: relative;
4286 display: inline-flex;
4287 align-items: center;
4288 justify-content: center;
4289 gap: .55rem;
4290 padding: .8rem 1.6rem;
4291 background: linear-gradient(135deg,
4292 var(--accent, #c2410c),
4293 color-mix(in srgb, var(--accent, #c2410c) 80%, #000));
4294 color: #fff;
4295 border: none;
4296 border-radius: 999px;
4297 font: inherit;
4298 font-weight: 600;
4299 font-size: .95rem;
4300 line-height: 1;
4301 letter-spacing: .01em;
4302 cursor: pointer;
4303 overflow: hidden;
4304 isolation: isolate;
4305 box-shadow:
4306 0 1px 0 rgba(255,255,255,.15) inset,
4307 0 -2px 0 rgba(0,0,0,.1) inset,
4308 0 4px 14px color-mix(in srgb, var(--accent, #c2410c) 40%, transparent),
4309 0 1px 3px rgba(0,0,0,.18);
4310 transition:
4311 transform .15s cubic-bezier(.4, 0, .2, 1),
4312 box-shadow .2s ease,
4313 filter .15s ease;
4314}
4315.install-app-btn svg {
4316 flex-shrink: 0;
4317 /* subtle bounce-on-hover trigger, separate animation */
4318 transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
4319}
4320.install-app-btn span {
4321 line-height: 1;
4322}
4323
4324/* Shimmer-streep die langzaam over de knop loopt — "alive" effect */
4325.install-app-btn::before {
4326 content: "";
4327 position: absolute;
4328 top: 0;
4329 left: -100%;
4330 width: 60%;
4331 height: 100%;
4332 background: linear-gradient(110deg,
4333 transparent 30%,
4334 rgba(255,255,255,.25) 50%,
4335 transparent 70%);
4336 z-index: -1;
4337 animation: pcmsInstallShimmer 4s ease-in-out infinite;
4338 pointer-events: none;
4339}
4340@keyframes pcmsInstallShimmer {
4341 0%, 35% { left: -100%; }
4342 65%, 100% { left: 200%; }
4343}
4344
4345.install-app-btn:hover {
4346 transform: translateY(-2px) scale(1.02);
4347 filter: brightness(1.06);
4348 box-shadow:
4349 0 1px 0 rgba(255,255,255,.2) inset,
4350 0 -2px 0 rgba(0,0,0,.1) inset,
4351 0 8px 24px color-mix(in srgb, var(--accent, #c2410c) 55%, transparent),
4352 0 2px 6px rgba(0,0,0,.2);
4353}
4354.install-app-btn:hover svg {
4355 transform: translateY(-2px);
4356}
4357.install-app-btn:active {
4358 transform: translateY(0) scale(.98);
4359 transition-duration: .05s;
4360}
4361.install-app-btn:focus-visible {
4362 outline: 2px solid var(--accent, #c2410c);
4363 outline-offset: 3px;
4364}
4365
4366/* Reduced motion: shimmer uit, alleen statisch */
4367@media (prefers-reduced-motion: reduce) {
4368 .install-app-btn::before { animation: none; left: -100%; }
4369 .install-app-btn:hover { transform: none; }
4370 .install-app-btn:hover svg { transform: none; }
4371}
4372
4373/* Install-instructions modal */
4374.install-modal {
4375 position: fixed;
4376 inset: 0;
4377 z-index: 10000;
4378 display: flex;
4379 align-items: center;
4380 justify-content: center;
4381 padding: 1rem;
4382}
4383.install-modal-backdrop {
4384 position: absolute;
4385 inset: 0;
4386 background: rgba(0,0,0,.55);
4387 backdrop-filter: blur(3px);
4388}
4389.install-modal-panel {
4390 position: relative;
4391 z-index: 1;
4392 background: var(--paper);
4393 color: var(--ink);
4394 border: 1px solid var(--rule);
4395 border-radius: 14px;
4396 padding: 1.5rem;
4397 max-width: 440px;
4398 width: 100%;
4399 max-height: 90vh;
4400 overflow-y: auto;
4401 box-shadow: 0 20px 60px rgba(0,0,0,.4);
4402}
4403.install-modal-panel h3 { font-size: 1.15rem; color: var(--ink); }
4404.install-modal-panel h4 {
4405 margin: 1rem 0 .4rem;
4406 font-size: .92rem;
4407 letter-spacing: .03em;
4408 text-transform: uppercase;
4409 opacity: .7;
4410 color: var(--ink);
4411}
4412.install-modal-panel p { color: var(--ink); }
4413.install-steps {
4414 margin: 0;
4415 padding-left: 1.35rem;
4416 display: flex;
4417 flex-direction: column;
4418 gap: .45rem;
4419 font-size: .95rem;
4420 line-height: 1.45;
4421 color: var(--ink);
4422}
4423.install-steps li::marker { color: var(--accent); font-weight: 700; }
4424.install-apk-block {
4425 margin-top: 1.25rem;
4426 padding-top: 1rem;
4427 border-top: 1px dashed var(--rule);
4428}
4429.install-apk-link {
4430 display: inline-flex;
4431 align-items: center;
4432 margin-top: .4rem;
4433 padding: .6rem 1rem;
4434 background: var(--accent);
4435 color: #fff;
4436 border-radius: 8px;
4437 text-decoration: none;
4438 font-weight: 600;
4439}
4440.install-apk-link:hover { filter: brightness(1.08); }
4441.install-modal-actions {
4442 display: flex;
4443 justify-content: flex-end;
4444 margin-top: 1.25rem;
4445}
4446.install-modal-actions .btn {
4447 padding: .5rem 1rem;
4448 background: var(--paper-2);
4449 border: 1px solid var(--rule);
4450 border-radius: 8px;
4451 color: var(--ink);
4452 cursor: pointer;
4453 font: inherit;
4454 font-weight: 500;
4455}
4456.install-modal-actions .btn:hover {
4457 background: color-mix(in srgb, var(--accent) 10%, var(--paper-2));
4458 border-color: var(--accent);
4459 color: var(--accent);
4460}
4461
4462@media (max-width: 520px) {
4463 .install-modal-panel { padding: 1.2rem; }
4464 .install-app-btn { width: 100%; justify-content: center; }
4465}
4466
4467/* v9.3 — Install-modal: choice-blocks met voor/nadelen */
4468.install-choice {
4469 margin-top: 1.25rem;
4470 padding: 1rem;
4471 border: 1px solid color-mix(in srgb, currentColor 15%, transparent);
4472 border-radius: 10px;
4473 background: color-mix(in srgb, currentColor 3%, transparent);
4474}
4475.install-choice + .install-choice { margin-top: 1rem; }
4476.install-choice h4 {
4477 margin: 0 0 .75rem;
4478 font-size: 1rem;
4479 letter-spacing: 0;
4480 text-transform: none;
4481 opacity: 1;
4482}
4483.install-pros-cons {
4484 display: flex;
4485 gap: 1rem;
4486 margin: .5rem 0 1rem;
4487}
4488.install-pros,
4489.install-cons {
4490 flex: 1;
4491 min-width: 0;
4492 font-size: .85rem;
4493 line-height: 1.45;
4494}
4495.install-pros strong,
4496.install-cons strong {
4497 display: block;
4498 margin-bottom: .35rem;
4499 font-size: .82rem;
4500 letter-spacing: .02em;
4501}
4502.install-pros strong { color: #16a34a; }
4503.install-cons strong { color: #dc2626; }
4504.install-pros ul,
4505.install-cons ul {
4506 margin: 0;
4507 padding-left: 1.1rem;
4508 display: flex;
4509 flex-direction: column;
4510 gap: .25rem;
4511}
4512.install-pros li::marker { color: #16a34a; }
4513.install-cons li::marker { color: #dc2626; }
4514
4515.install-choice-cta {
4516 display: inline-flex;
4517 align-items: center;
4518 justify-content: center;
4519 gap: .35rem;
4520 margin-top: .5rem;
4521 padding: .7rem 1.1rem;
4522 background: var(--accent, #c2410c);
4523 color: #fff;
4524 border: none;
4525 border-radius: 8px;
4526 text-decoration: none;
4527 font: inherit;
4528 font-weight: 600;
4529 font-size: .95rem;
4530 cursor: pointer;
4531 transition: filter .12s ease;
4532}
4533.install-choice-cta:hover { filter: brightness(1.08); }
4534.install-choice-note {
4535 margin: .5rem 0 0;
4536 padding: .6rem .8rem;
4537 background: color-mix(in srgb, currentColor 4%, transparent);
4538 border-left: 3px solid var(--accent, #c2410c);
4539 border-radius: 4px;
4540 font-size: .9rem;
4541 line-height: 1.45;
4542}
4543
4544@media (max-width: 520px) {
4545 .install-pros-cons { flex-direction: column; gap: .75rem; }
4546}
4547
4548/* v9.4 — Soft fade-overgang tussen posts bij navigatie.
4549 Fade-out is rustig (450ms): oude content vervaagt geleidelijk terwijl
4550 de scroll-naar-top loopt. Fade-in is snel (180ms) met een lichte blur-
4551 onscherp → scherp animatie zodat de nieuwe content niet abrupt verschijnt. */
4552#pcms-main {
4553 transition: opacity .45s ease-out;
4554}
4555#pcms-main.is-pcms-transitioning-out {
4556 opacity: 0;
4557}
4558#pcms-main.is-pcms-transitioning-in {
4559 opacity: 0;
4560 filter: blur(6px);
4561 animation: pcmsFadeIn .18s ease-out forwards;
4562 will-change: opacity, filter;
4563}
4564@keyframes pcmsFadeIn {
4565 from { opacity: 0; filter: blur(6px); }
4566 to { opacity: 1; filter: blur(0); }
4567}
4568
4569/* Respecteer reduced-motion voorkeur (iOS/Android accessibility setting) */
4570@media (prefers-reduced-motion: reduce) {
4571 #pcms-main {
4572 transition: opacity .15s ease-out;
4573 }
4574 #pcms-main.is-pcms-transitioning-in {
4575 filter: none;
4576 animation: none;
4577 opacity: 1;
4578 }
4579}
4580
4581/* === Fediverse interactions — inherits the native .comment styling === */
4582.post-fediverse .fedi-stats { display: flex; gap: .45rem; margin: .35rem 0 1.5rem; align-items: center; }
4583.post-fediverse .fedi-stat {
4584 display: inline-flex; align-items: center; gap: .4rem;
4585 padding: .32rem .7rem; border-radius: 999px; font-size: .85rem; line-height: 1;
4586 font-variant-numeric: tabular-nums;
4587 color: var(--ink-muted); background: transparent;
4588 border: 1px solid var(--rule);
4589}
4590.post-fediverse .fedi-stat svg { width: 15px; height: 15px; }
4591.post-fediverse .fedi-stat-btn { cursor: pointer; font: inherit; line-height: 1; transition: color .15s, border-color .15s, background .15s; }
4592.post-fediverse .fedi-stat-btn:hover { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, var(--rule)); background: var(--accent-tint); }
4593.post-fediverse .fedi-stat-btn:hover svg { fill: color-mix(in srgb, var(--accent) 22%, transparent); }
4594.post-fediverse .fedi-handle { color: var(--ink-soft, #888); font-size: .82rem; }
4595.post-fediverse .comment-content p { margin: .2rem 0; }
4596.post-fediverse .comment-content p:first-child { margin-top: 0; }
4597.post-fediverse .comment-content p:last-child { margin-bottom: 0; }
4598/* reply toggle: a plain "Reageer" action like the comment buttons (no triangle) */
4599.post-fediverse .fedi-reply-toggle { list-style: none; cursor: pointer; display: inline-block; }
4600.post-fediverse .fedi-reply-toggle::-webkit-details-marker { display: none; }
4601.post-fediverse details[open] .fedi-reply-toggle { margin-bottom: .5rem; }
4602
4603/* Reply-via-fediverse CTA on post pages */
4604.post-fediverse-cta { margin: 1.75rem 0; }
4605.fedi-remote-reply-btn { display: inline-flex; align-items: center; gap: .45rem; }
4606.post-fediverse-cta .fedi-remote-reply-btn {
4607 border: 1px solid color-mix(in srgb, var(--accent, #888) 55%, transparent);
4608 background: color-mix(in srgb, var(--accent, #888) 10%, transparent);
4609 color: var(--ink, inherit); border-radius: 999px; padding: .5rem 1.05rem;
4610 font-weight: 600; cursor: pointer; transition: background .15s ease;
4611}
4612.post-fediverse-cta .fedi-remote-reply-btn:hover { background: color-mix(in srgb, var(--accent, #888) 22%, transparent); }
4613.post-fediverse-cta .fedi-remote-reply-btn svg { color: var(--accent, currentColor); }
4614.post-fediverse .comment-actions .fedi-remote-reply-btn { gap: .3rem; }
4615
4616/* Inline "reply via fediverse" address form (replaces the browser prompt) */
4617.fedi-remote-form {
4618 position: absolute; z-index: 60; display: inline-flex; align-items: center; gap: .4rem;
4619 padding: .4rem; border-radius: 999px;
4620 background: var(--paper-2, var(--paper, #fff));
4621 border: 1px solid color-mix(in srgb, var(--ink, #000) 12%, transparent);
4622 box-shadow: 0 10px 30px rgba(0,0,0,.28);
4623}
4624.fedi-remote-form input {
4625 height: 2.2rem; padding: 0 .9rem; border-radius: 999px; font: inherit; min-width: 230px;
4626 border: 1px solid color-mix(in srgb, var(--ink, #000) 18%, transparent);
4627 background: color-mix(in srgb, var(--ink, #000) 4%, transparent); color: var(--ink, #000);
4628}
4629.fedi-remote-form input::placeholder { color: var(--ink-soft, #999); }
4630.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); }
4631.fedi-remote-form .fedi-remote-go {
4632 height: 2.2rem; min-width: 2.2rem; padding: 0 .85rem; border-radius: 999px;
4633 display: inline-flex; align-items: center; justify-content: center; font-size: 1rem;
4634}
4635.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; }
4636.fedi-remote-form .fedi-remote-cancel:hover { color: var(--ink, #000); }
4637
4638/* ── NSFW / sensitive content — blur + click to reveal ───────────────── */
4639.nsfw-media { position: relative; }
4640.nsfw-veil {
4641 position: absolute; inset: 0; z-index: 4; cursor: pointer; border-radius: inherit;
4642 display: flex; flex-direction: column; align-items: center; justify-content: center;
4643 gap: .5rem; padding: .75rem; text-align: center;
4644 background: color-mix(in srgb, var(--paper, #14141a) 50%, transparent);
4645 backdrop-filter: blur(22px) saturate(.6); -webkit-backdrop-filter: blur(22px) saturate(.6);
4646}
4647.nsfw-media.is-shown > .nsfw-veil { display: none; }
4648.nsfw-veil-label { font-weight: 700; font-size: .82rem; color: var(--ink, #f3f1ea); text-shadow: 0 1px 2px rgba(0,0,0,.5); }
4649.nsfw-veil-btn {
4650 font-size: .72rem; font-weight: 600; padding: .3rem .8rem; border-radius: 999px;
4651 border: 1px solid color-mix(in srgb, var(--ink, #fff) 55%, transparent);
4652 background: color-mix(in srgb, var(--paper, #000) 35%, transparent); color: var(--ink, #f3f1ea);
4653}
4654/* Post page: blur cover + body behind a content-warning banner until revealed */
4655.nsfw-gate .post-cover,
4656.nsfw-gate .post-content { filter: blur(26px); pointer-events: none; user-select: none; transition: filter .2s ease; }
4657.nsfw-gate.is-shown .post-cover,
4658.nsfw-gate.is-shown .post-content { filter: none; pointer-events: auto; user-select: auto; }
4659.nsfw-banner {
4660 display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; margin: 0 0 1.5rem;
4661 padding: .8rem 1rem; border-radius: 12px;
4662 border: 1px solid color-mix(in srgb, var(--accent, #e8b04b) 45%, transparent);
4663 background: color-mix(in srgb, var(--accent, #e8b04b) 9%, transparent);
4664}
4665.nsfw-gate.is-shown .nsfw-banner { display: none; }
4666.nsfw-banner-icon { font-size: 1.2rem; }
4667.nsfw-banner-text { font-weight: 600; font-size: .92rem; color: var(--ink); }
4668.nsfw-banner-btn {
4669 margin-left: auto; cursor: pointer; font: inherit; font-size: .82rem; font-weight: 600;
4670 padding: .4rem 1rem; border-radius: 999px; border: 0;
4671 background: var(--accent, #e8b04b); color: #1a1205;
4672}
Note: See TracBrowser for help on using the repository browser.