source: Klonkt/src/assets/css/style.css@ 0ca7e9a4

main
Last change on this file since 0ca7e9a4 was 1f640ff, checked in by Robin <roboburr@…>, 6 weeks ago

Audio-tegel: golfvorm en titel elk hun eigen band, en balkjes ipv de rauwe golf

De titel stond dwars door de golfvorm heen (Robins schermafdruk): de
golfvorm hing absoluut gecentreerd en de flex-tegel centreerde de titel
er bovenop. Nu heeft elk zijn eigen band: golfvorm in de bovenhelft
(8-54 procent), titel op 60 procent, bronregel op 76. De maten staan
expliciet: een absoluut gepositioneerde img valt bij width/height auto
terug op zijn intrinsieke maat en de band klapte dicht.

En de golfvorm zelf is mooier (Robins tweede vraag): geen harige rauwe
golf meer maar balkjes in SoundCloud-stijl. Peak en average worden op 57
kolommen gesampled (zachte piek-top over heldere kern), nearest-neighbor
opgeblazen tot balkjes van 14px, en drawgrid wist er transparante
spleetjes van 5px tussen (c=black@0 met replace=1 schrijft echte
transparantie).

Changed files:
src/routes/activitypub.js

  • het showwavespic-recept vervangen door de gelaagde balkjes-graph

src/views/partials/post-tile.ejs

  • grid-tile-audio-klasse op de anchor als er een golfvorm is

src/assets/css/style.css

  • grid-tile-wave: expliciete band (top 8, hoogte 46, breedte 84)
  • grid-tile-audio: titel op 60 procent, bronregel op 76

remarks: geometrie numeriek geverifieerd in een browser-preview (golf
17.6-44.4 procent, titel 60-65.2, 58px ruimte, gradient intact) en het
balkjes-recept visueel beoordeeld op een tegel-gradient-compositie. De
bestaande audiopost houdt zijn oude dunne golfvorm-png; een verse upload
krijgt de balkjes. 345 tests groen.

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

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