PageSourceSearch

https://fablab66.fr/

html fablab66.fr collected 2026-09-24 14:21:34 UTC 78,113 bytes, 1,539 lines download raw bytes

1<!doctype html>
2<html lang="fr" class="h-full">
3<head>
4  <meta charset="utf-8">
5  <meta name="viewport" content="width=device-width, initial-scale=1">
6  <meta name="color-scheme" content="light dark">
7  <title>FabLab66 — Communauté des makers des Pyrénées-Orientales</title>
8  <link rel="icon" href="/static/img/favicon.ico" sizes="any">
9  <link rel="icon" href="/static/img/favicon-64.png" type="image/png" sizes="64x64">
10  <link rel="apple-touch-icon" href="/static/img/favicon-180.png">
11
12  
13  <meta name="description" content="FabLab66 relie fablabs, tiers-lieux et makers des Pyrénées-Orientales. Projets documentés, matériel partagé, ateliers.">
14  <link rel="canonical" href="https://fablab66.fr/">
15  <meta property="og:site_name" content="FabLab66">
16  <meta property="og:locale" content="fr_FR">
17  <meta property="og:type" content="website">
18  <meta property="og:title" content="FabLab66 — Communauté des makers des Pyrénées-Orientales">
19  <meta property="og:description" content="FabLab66 relie fablabs, tiers-lieux et makers des Pyrénées-Orientales. Projets documentés, matériel partagé, ateliers.">
20  <meta property="og:url" content="https://fablab66.fr/">
21  <meta property="og:image" content="https://fablab66.fr/static/img/logo.png">
22  <meta name="twitter:card" content="summary_large_image">
23  <meta name="twitter:title" content="FabLab66 — Communauté des makers des Pyrénées-Orientales">
24  <meta name="twitter:description" content="FabLab66 relie fablabs, tiers-lieux et makers des Pyrénées-Orientales. Projets documentés, matériel partagé, ateliers.">
25  <meta name="twitter:image" content="https://fablab66.fr/static/img/logo.png">
26
27  
27<script>
28    // Apply theme BEFORE first paint to avoid flash.
29    (function () {
30      try {
31        var stored = localStorage.getItem('theme');
32        var systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
33        var dark = stored === 'dark' || (stored === null && systemDark);
34        if (dark) document.documentElement.classList.add('dark');
35      } catch (_) {}
36    })();
37  </script>
37
38
39  
39<script src="https://cdn.tailwindcss.com"></script>
39
40  
40<script src="https://unpkg.com/[email protected]" defer></script>
40
41  
41<script>
42    tailwind.config = {
43      darkMode: 'class',
44      theme: {
45        extend: {
46          colors: {
47            brand: {
48              50:  '#f0f7fd', 100: '#d9eafa', 200: '#b2d5f5', 300: '#7fb8ed',
49              400: '#4a9be3', 500: '#1F88DB', 600: '#166fb8', 700: '#135a95',
50              800: '#124b78', 900: '#123f64'
51            }
52          },
53          fontFamily: { sans: ['Inter','ui-sans-serif','system-ui'] }
54        }
55      }
56    }
57  </script>
57
58  <link rel="preconnect" href="https://fonts.googleapis.com">
59  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
60
61  
62  <link rel="stylesheet"
63        href="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/github.min.css"
64        media="(prefers-color-scheme: light)">
65  <link rel="stylesheet"
66        href="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/github-dark.min.css"
67        media="(prefers-color-scheme: dark)">
68  
68<script defer src="https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js"></script>
68
69
70  
71  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/cropper.min.css">
72
73  
74</head>
75<body class="min-h-full flex flex-col bg-slate-50 text-slate-800 font-sans antialiased
76             dark:bg-slate-950 dark:text-slate-200">
77  <nav class="bg-white border-b border-slate-200 sticky top-0 z-40
78            dark:bg-slate-900 dark:border-slate-800">
79  <div class="max-w-5xl mx-auto px-4">
80
81    
82    <div class="h-14 flex items-center justify-between gap-2">
83
84      
85      <a href="/"
86         class="flex items-center gap-2 font-bold text-brand-700 dark:text-brand-400 text-lg shrink-0">
87        <img src="/static/img/logo.png" alt="FabLab66" class="w-9 h-9">
88        <span class="hidden xs:inline">FabLab66</span>
89      </a>
90
91      
92      <div class="hidden sm:flex items-center gap-1 sm:gap-2 text-sm flex-1 justify-end">
93        <a class="px-2.5 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 whitespace-nowrap" href="/posts/">Feed</a>
94        <a class="px-2.5 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 whitespace-nowrap" href="/projects/">Projets</a>
95        <a class="px-2.5 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 whitespace-nowrap hidden md:inline" href="/equipment/">
95Matériel</a>
96        <a class="px-2.5 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 whitespace-nowrap hidden md:inline" href="/events/">Événements</a>
97        <a class="px-2.5 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 whitespace-nowrap hidden lg:inline" href="/communities/">Communautés</a>
98        <a class="px-2.5 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 whitespace-nowrap hidden md:inline" href="/membres">Membres</a>
99
100        <button type="button" onclick="window.__toggleTheme()"
101                class="p-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-300"
102                title="Changer de thème" aria-label="Changer de thème">
103          <svg class="w-5 h-5 hidden dark:block" fill="none" viewBox="0 0 24 24" stroke-width="1.75" stroke="currentColor">
104            <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364 1.386-1.591 1.591M21 12h-2.25m-1.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"/>
105          </svg>
106          <svg class="w-5 h-5 dark:hidden" fill="none" viewBox="0 0 24 24" stroke-width="1.75" stroke="currentColor">
107            <path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"/>
108          </svg>
109        </button>
110
111        
112          <a href="/auth/login"
113             class="px-2.5 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 whitespace-nowrap">Se connecter</a>
114          <a href="/auth/register"
115             class="px-2.5 py-1.5 rounded-lg bg-brand-500 text-white hover:bg-brand-600 whitespace-nowrap">Créer un compte</a>
116        
117      </div>
118
119      
120      <div class="flex sm:hidden items-center gap-1">
121        
122        <button type="button" id="nav-burger"
123                class="p-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-300"
124                aria-label="Menu" aria-expanded="false" aria-controls="mobile-menu">
125          <svg id="burger-icon" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
126            <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/>
127          </svg>
128          <svg id="burger-close-icon" class="w-5 h-5 hidden" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
129            <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
130          </svg>
131        </button>
132      </div>
133    </div>
134
135    
136    <div id="mobile-menu" class="hidden sm:hidden border-t border-slate-200 dark:border-slate-800 py-3 space-y-0.5 text-sm">
137
138      
139      <a href="/posts/"
140         class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
141        Feed
142      </a>
143      <a href="/projects/"
144         class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
145        Projets
146      </a>
147      <a href="/equipment/"
148         class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
149        Matériel
150      </a>
151      <a href="/events/"
152         class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
153        Événements
154      </a>
155      <a href="/communities/"
156         class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
157        Communautés
158      </a>
159      <a href="/membres"
160         class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
161        Membres
162      </a>
163
164      
165      <button type="button" onclick="window.__toggleTheme()"
166              class="w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dar
166k:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
167        <svg class="w-4 h-4 hidden dark:block" fill="none" viewBox="0 0 24 24" stroke-width="1.75" stroke="currentColor">
168          <path stroke-linecap="round" stroke-linejoin="round" d="M12 3v2.25m6.364 1.386-1.591 1.591M21 12h-2.25m-1.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"/>
169        </svg>
170        <svg class="w-4 h-4 dark:hidden" fill="none" viewBox="0 0 24 24" stroke-width="1.75" stroke="currentColor">
171          <path stroke-linecap="round" stroke-linejoin="round" d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"/>
172        </svg>
173        Changer de thème
174      </button>
175
176      <div class="my-1 border-t border-slate-100 dark:border-slate-800"></div>
177
178      
179        <a href="/auth/login"
180           class="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-200">
181          Se connecter
182        </a>
183        <a href="/auth/register"
184           class="flex items-center gap-3 mx-3 my-1 px-4 py-2 rounded-lg bg-brand-500 text-white hover:bg-brand-600 font-medium justify-center">
185          Créer un compte
186        </a>
187      
188    </div>
189
190  </div>
191</nav>
192
193<script>
194  // Admin dropdown close on outside click
195  document.addEventListener('click', function(e) {
196    var wrap = document.querySelector('[data-admin-dropdown]');
197    var menu = document.getElementById('admin-menu');
198    if (wrap && menu && !wrap.contains(e.target)) menu.classList.add('hidden');
199  });
200
201  // Mobile burger toggle
202  (function() {
203    var burger = document.getElementById('nav-burger');
204    var menu = document.getElementById('mobile-menu');
205    var iconOpen = document.getElementById('burger-icon');
206    var iconClose = document.getElementById('burger-close-icon');
207    if (!burger || !menu) return;
208    burger.addEventListener('click', function() {
209      var open = !menu.classList.contains('hidden');
210      menu.classList.toggle('hidden', open);
211      iconOpen.classList.toggle('hidden', !open);
212      iconClose.classList.toggle('hidden', open);
213      burger.setAttribute('aria-expanded', String(!open));
214    });
215  })();
216</script>
216
217
218  
219    
220  
221
222  <main class="flex-1 w-full">
223    
224  
225  <section class="bg-gradient-to-br from-brand-50 via-white to-slate-50 border-b border-slate-200
226                  dark:from-brand-900/30 dark:via-slate-950 dark:to-slate-950 dark:border-slate-800">
227    <div class="max-w-5xl mx-auto px-4 py-16 sm:py-24 text-center">
228      <img src="/static/img/logo.png" alt="FabLab66"
229           class="w-28 h-28 sm:w-32 sm:h-32 mx-auto mb-6 drop-shadow-sm">
230      <h1 class="text-4xl sm:text-5xl font-bold text-slate-900 dark:text-white tracking-tight">
231        Fabriquer, apprendre, partager <span class="text-brand-500">ensemble</span>
232      </h1>
233      <p class="mt-4 max-w-2xl mx-auto text-slate-600 dark:text-slate-300 text-lg">
234        La plateforme qui relie fablabs, tiers-lieux, associations et bricoleurs
235        des Pyrénées-Orientales. Documentez vos projets, partagez votre matériel,
236        proposez ou rejoignez des formations.
237      </p>
238      <div class="mt-8 flex flex-wrap justify-center gap-3">
239        
240          <a href="/auth/register" class="px-5 py-2.5 rounded-lg bg-brand-500 text-white font-medium hover:bg-brand-600">Créer un compte</a>
241          <a href="/auth/login"
242             class="px-5 py-2.5 rounded-lg bg-white border border-slate-300 hover:bg-slate-50
243                    dark:bg-slate-900 dark:border-slate-700 dark:hover:bg-slate-800 dark:text-slate-100">Se connecter</a>
244        
245      </div>
246    </div>
247  </section>
248
249  
250  <section class="bg-white dark:bg-slate-900 border-b border-slate-200 dark:border-slate-800">
251    <div class="max-w-5xl mx-auto px-4 py-6 grid grid-cols-2 sm:grid-cols-4 gap-4 text-center">
252      
253        <a href="/projects/" class="block hover:opacity-80 transition">
254          <div class="text-3xl font-bold text-brand-600 dark:text-brand-400">233</div>
255          <div class="text-xs uppercase tracking-wide text-slate-500 dark:text-slate-400 mt-1">Projets</div>
256        </a>
257      
258        <a href="/communities/" class="block hover:opacity-80 transition">
259          <div class="text-3xl font-bold text-brand-600 dark:text-brand-400">4</div>
260          <div class="text-xs uppercase tracking-wide text-slate-500 dark:text-slate-400 mt-1">Communautés</div>
261        </a>
262      
263        <a href="/events/" class="block hover:opacity-80 transition">
264          <div class="text-3xl font-bold text-brand-600 dark:text-brand-400">0</div>
265          <div class="text-xs uppercase tracking-wide text-slate-500 dark:text-slate-400 mt-1">Événements</div>
266        </a>
267      
268        <div>
269          <div class="text-3xl font-bold text-brand-600 dark:text-brand-400">24</div>
270          <div class="text-xs uppercase tracking-wide text-slate-500 dark:text-slate-400 mt-1">Makers</div>
271        </div>
272      
273    </div>
274  </section>
275
276  
277  
278    <section class="max-w-6xl mx-auto px-4 py-12">
279      <div class="flex items-end justify-between mb-6 gap-3 flex-wrap">
280        <div>
281          <h2 class="text-2xl font-bold text-slate-900 dark:text-white">Projets récents</h2>
282          <p class="text-sm text-slate-500 dark:text-slate-400 mt-1">Les dernières créations partagées par la communauté.</p>
283        </div>
284        <a href="/projects/"
285           class="text-sm text-brand-600 dark:text-brand-400 hover:underline">Tous les projets →</a>
286      </div>
287
288      <div class="relative group" data-carousel>
289        <button type="button" data-carousel-prev
290                class="hidden md:grid absolute -left-4 top-1/2 -translate-y-1/2 z-10 w-10 h-10 rounded-full bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 shadow-md place-items-center text-slate-700 dark:text-slate-200 hover:bg-brand-50 hover:text-brand-600 dark:hover:bg-brand-900/40 dark:hover:text-brand-300 opacity-0 group-hover:opacity-100 transition"
291                aria-label="Précédent">
292          <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
293            <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5"/>
294          </svg>
295        </button>
296        <button type="button" data-carousel-next
297                class="hidden md:grid absolute -right-4 top-1/2 -translate-y-1/2 z-10 w-10 h-10 rounded-full bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 shadow-md place-items-center text-slate-700 dark:text-slate-200 hover:bg-brand-50 hover:text-brand-600 dark:hover:bg-brand-900/40 dark:hover:text-brand-300 opacity-0 group-hover:opacity-100 transition"
298                aria-label="Suivant">
299          <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
300            <path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5"/>
301          </svg>
302        </button>
303
304        <div data-carousel-track
305             class="flex gap-5 overflow-x-auto snap-x snap-mandatory scroll-smooth pb-4 -mx-4 px-4"
306             style="scrollbar-width: thin;">
307          
308            
309              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
310                
311<a href="/projects/jukebox-20"
312   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
313  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
314    
315      <img src="/uploads/project_covers/4c7980e6ec284d85bdbc2d85f73e3ec6.jpg"
316           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
317    
318  </div>
319  <div class="p-4">
320    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
321      JukeBox 2.0
322      
323        <span class="ml-1 text-xs font-medium px-1.5 py-0.5 rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300">🚧 en cours</span>
324      
325    </h2>
326    
327      <p class="mt-1 text-sm text-slate-600 dark:text-slate-400 line-clamp-2">Redonner vie à un jukebox de 1972 Century 21</p>
328    
329    <div class="mt-3 flex flex-wrap gap-1.5">
330      
331        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">Musique</span>
332      
333      
334        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 FabLab Maillol</span>
335      
336    </div>
337    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
338      <span class="truncate">par Fabien</span>
339      <span class="flex items-center gap-2 shrink-0">
340        <span class="inline-flex items-center gap-1" title="J'aime">
341          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
342            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
343          </svg>
344          0
345        </span>
346        <span class="inline-flex items-center gap-1" title="Consultations">
347          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
348            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
349            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
350          </svg>
351          319
352        </span>
353        <span class="inline-flex items-center gap-1" title="Commentaires">
354          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
355            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
356          </svg>
357          0
358        </span>
359        
360      </span>
361    </div>
362  </div>
363</a>
364              </div>
365            
366          
367            
368              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
369                
370<a href="/projects/antenne-parabolique-amplication-4g"
371   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
372  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
373    
374      <img src="/uploads/project_covers/e46785cfc68744b2aad7da1a5137e00f.png"
375           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
376    
377  </div>
378  <div class="p-4">
379    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
380      Antenne parabolique amplication 4G
381      
382        <span class="ml-1 text-xs font-medium px-1.5 py-0.5 rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300">🚧 en cours</span>
383      
384    </h2>
385    
386      <p class="mt-1 text-sm text-slate-600 dark:text-slate-400 line-clamp-2">Réflecteur Parabolique Passif pour Routeur 4G Huawei</p>
387    
388    <div class="mt-3 flex flex-wrap gap-1.5">
389      
390        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">Vie quotidienne</span>
391      
392      
393        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 Mobilab 66</span>
394      
395    </div>
396    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
397      <span class="truncate">par Fabien</span>
398      <span class="flex items-center gap-2 shrink-0">
399        <span class="inline-flex items-center gap-1" title="J'aime">
400          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
401            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
402          </svg>
403          0
404        </span>
405        <span class="inline-flex items-center gap-1" title="Consultations">
406          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
407            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
408            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
409          </svg>
410          208
411        </span>
412        <span class="inline-flex items-center gap-1" title="Commentaires">
413          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
414            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
415          </svg>
416          0
417        </span>
418        
419      </span>
420    </div>
421  </div>
422</a>
423              </div>
424            
425          
426            
427              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
428                
429<a href="/projects/subaru-impreza-rc-110"
430   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
431  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
432    
433      <img src="/uploads/project_covers/4f77ce0c3cba4f8bb1d1d6a937416188.jpg"
434           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
435    
436  </div>
437  <div class="p-4">
438    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
439      Subaru Impreza RC 1/10
440      
441    </h2>
442    
443      <p class="mt-1 text-sm text-slate-600 dark:text-slate-400 line-clamp-2">Impression 3D, Raspberry Pi, et 4G.</p>
444    
445    <div class="mt-3 flex flex-wrap gap-1.5">
446      
447        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">Robotique</span>
448      
449      
450        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 La Cyber Fabrique</span>
451      
452    </div>
453    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
454      <span class="truncate">par Kévin CHAILLY</span>
455      <span class="flex items-center gap-2 shrink-0">
456        <span class="inline-flex items-center gap-1" title="J'aime">
457          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
458            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
459          </svg>
460          0
461        </span>
462        <span class="inline-flex items-center gap-1" title="Consultations">
463          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
464            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
464
465            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
466          </svg>
467          329
468        </span>
469        <span class="inline-flex items-center gap-1" title="Commentaires">
470          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
471            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
472          </svg>
473          0
474        </span>
475        <span>05/07/2026</span>
476      </span>
477    </div>
478  </div>
479</a>
480              </div>
481            
482          
483            
484              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
485                
486<a href="/projects/cyberdeck"
487   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
488  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
489    
490      <img src="/uploads/project_covers/fff5d6511b7a4b90836f7c4beebceb3e.jpg"
491           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
492    
493  </div>
494  <div class="p-4">
495    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
496      Cyberdeck
497      
498    </h2>
499    
500      <p class="mt-1 text-sm text-slate-600 dark:text-slate-400 line-clamp-2">Un PC Fixe dans une Pelicase</p>
501    
502    <div class="mt-3 flex flex-wrap gap-1.5">
503      
504        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">Jeux</span>
505      
506      
507        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 La Cyber Fabrique</span>
508      
509    </div>
510    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
511      <span class="truncate">par Kévin CHAILLY</span>
512      <span class="flex items-center gap-2 shrink-0">
513        <span class="inline-flex items-center gap-1" title="J'aime">
514          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
515            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
516          </svg>
517          1
518        </span>
519        <span class="inline-flex items-center gap-1" title="Consultations">
520          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
521            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
522            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
523          </svg>
524          402
525        </span>
526        <span class="inline-flex items-center gap-1" title="Commentaires">
527          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
528            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
529          </svg>
530          0
531        </span>
532        <span>05/07/2026</span>
533      </span>
534    </div>
535  </div>
536</a>
537              </div>
538            
539          
540            
541              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
542                
543<a href="/projects/cnc-mpcnc-3-axes"
544   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
545  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
546    
547      <img src="/uploads/project_covers/6497faea5ea143bc820d016c24a33f38.jpg"
548           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
549    
550  </div>
551  <div class="p-4">
552    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
553      CNC MPCNC 3 Axes
554      
555    </h2>
556    
557      <p class="mt-1 text-sm text-slate-600 dark:text-slate-400 line-clamp-2">Projet de construction d&#39;une CNC mpcnc 3 axes</p>
558    
559    <div class="mt-3 flex flex-wrap gap-1.5">
560      
561        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">Autre</span>
562      
563      
564        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 La Cyber Fabrique</span>
565      
566    </div>
567    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
568      <span class="truncate">par Kévin CHAILLY</span>
569      <span class="flex items-center gap-2 shrink-0">
570        <span class="inline-flex items-center gap-1" title="J'aime">
571          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
572            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
573          </svg>
574          1
575        </span>
576        <span class="inline-flex items-center gap-1" title="Consultations">
577          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
578            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
579            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
580          </svg>
581          324
582        </span>
583        <span class="inline-flex items-center gap-1" title="Commentaires">
584          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
585            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
586          </svg>
587          1
588        </span>
589        <span>05/07/2026</span>
590      </span>
591    </div>
592  </div>
593</a>
594              </div>
595            
596          
597            
598              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
599                
600<a href="/projects/support-pour-panneaux-solaire"
601   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
602  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
603    
604      <img src="/uploads/project_covers/6fe6612229394dc88f73eb2bc46547d6.jpg"
605           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
606    
607  </div>
608  <div class="p-4">
609    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
610      Support pour panneaux solaire
611      
612    </h2>
613    
614      <p class="mt-1 text-sm text-slate-600 dark:text-slate-400 line-clamp-2">Ce support sert à accrocher un panneau solaire sur un trépied de chantier, afin de faciliter l&#39;installation et le déplacement des panneaux.</p>
615    
616    <div class="mt-3 flex flex-wrap gap-1.5">
617      
618        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">Vie quotidienne</span>
619      
620      
621        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 La Cyber Fabrique</span>
622      
623    </div>
624    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
625      <span class="truncate">par Romain Llapasset</span>
626      <span class="flex items-center gap-2 shrink-0">
627        <span class="inline-flex items-center gap-1" title="J'aime">
628          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
629            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
630          </svg>
631          0
632        </span>
633        <span class="inline-flex items-center gap-1" title="Consultations">
634          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
635            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
636            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
637          </svg>
638          397
639        </span>
640        <span class="inline-flex items-center gap-1" title="Commentaires">
641          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
642            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
643          </svg>
644          0
645        </span>
646        <span>04/07/2026</span>
647      </span>
648    </div>
649  </div>
650</a>
651              </div>
652            
653          
654            
655              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
656                
657<a href="/projects/salon-de-jardin"
658   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
659  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
660    
661      <img src="/uploads/project_covers/91f8c66dd9b84cc8afd587c1c2c3273c.jpg"
662           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
663    
664  </div>
665  <div class="p-4">
666    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
667      Salon de jardin
668      
669    </h2>
670    
671    <div class="mt-3 flex flex-wrap gap-1.5">
672      
673      
674        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 Mobilab 66</span>
675      
676    </div>
677    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
678      <span class="truncate">par Pierre</span>
679      <span class="flex items-center gap-2 shrink-0">
680        <span class="inline-flex items-center gap-1" title="J'aime">
681          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
682            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
683          </svg>
684          0
685        </span>
686        <span class="inline-flex items-center gap-1" title="Consultations">
687          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
688            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
689            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
690          </svg>
691          332
692        </span>
693        <span class="inline-flex items-center gap-1" title="Commentaires">
694          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
695            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
696          </svg>
697          0
698        </span>
699        <span>10/12/2025</span>
700      </span>
701    </div>
702  </div>
703</a>
704              </div>
705            
706          
707            
708              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
709                
710<a href="/projects/logo-aristide-maillol-bi-couleur"
711   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
712  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
713    
714      <img src="/uploads/project_covers/139178da2db641b1ba6505db4ed26651.png"
715           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
716    
717  </div>
718  <div class="p-4">
719    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
720      Logo Aristide Maillol (bi couleur)
721      
722    </h2>
723    
724    <div class="mt-3 flex flex-wrap gap-1.5">
725      
726      
727        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 FabLab Maillol</span>
728      
729    </div>
730    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
731      <span class="truncate">par Dewey Satre</span>
732      <span class="flex items-center gap-2 shrink-0">
733        <span class="inline-flex items-center gap-1" title="J'aime">
734          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
735            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
736          </svg>
737          0
738        </span>
739        <span class="inline-flex items-center gap-1" title="Consultations">
740          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
741            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
742            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
743          </svg>
744          384
745        </span>
746        <span class="inline-flex items-center gap-1" title="Commentaires">
747          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
748            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
749          </svg>
750          0
751        </span>
752        <span>09/12/2025</span>
753      </span>
754    </div>
755  </div>
756</a>
757              </div>
758            
759          
760            
761              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
762                
763<a href="/projects/bracelet-ou-porte-cles-connecte-nfc"
764   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
765  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
766    
767      <img src="/uploads/project_covers/acc827f1dc09495585ac77cf85aeab49.jpeg"
768           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
769    
770  </div>
771  <div class="p-4">
772    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
773      Bracelet ou porte-clés connecté NFC
774      
775    </h2>
776    
777    <div class="mt-3 flex flex-wrap gap-1.5">
778      
779      
780        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 Mobilab 66</span>
781      
782    </div>
783    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
784      <span class="truncate">par Fabien</span>
785      <span class="flex items-center gap-2 shrink-0">
786        <span class="inline-flex items-center gap-1" title="J'aime">
787          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
788            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
789          </svg>
790          0
791        </span>
792        <span class="inline-flex items-center gap-1" title="Consultations">
793          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
794            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
795            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
796          </svg>
797          336
798        </span>
799        <span class="inline-flex items-center gap-1" title="Commentaires">
800          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
801            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
802          </svg>
803          0
804        </span>
805        <span>06/08/2025</span>
806      </span>
807    </div>
808  </div>
809</a>
810              </div>
811            
812          
813            
814              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
815                
816<a href="/projects/capteur-connecte"
817   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
818  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
819    
820      <img src="/uploads/project_covers/a8c05fada41c4e6c8d7f34bbbf62b7db.jpg"
821           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
822    
823  </div>
824  <div class="p-4">
825    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
826      Capteur connecté
827      
828    </h2>
829    
830    <div class="mt-3 flex flex-wrap gap-1.5">
831      
832        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">Capteurs</span>
833      
834        <span class="text-xs px-2 py-0.5 rounded-full bg-brand-50 text-brand-700 dark:bg-brand-900/40 dark:text-brand-300">MicroContrôleur Esp</span>
835      
836      
837        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 Mobilab 66</span>
838      
839    </div>
840    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
841      <span class="truncate">par Fabien</span>
842      <span class="flex items-center gap-2 shrink-0">
843        <span class="inline-flex items-center gap-1" title="J'aime">
844          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
845            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
846          </svg>
847          0
848        </span>
849        <span class="inline-flex items-center gap-1" title="Consultations">
850          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
851            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
852            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
853          </svg>
854          324
855        </span>
856        <span class="inline-flex items-center gap-1" title="Commentaires">
857          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
858            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
859          </svg>
860          0
861        </span>
862        <span>27/01/2025</span>
863      </span>
864    </div>
865  </div>
866</a>
867              </div>
868            
869          
870            
871              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
872                
873<a href="/projects/support-manche-aspirateur-dyson"
874   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
875  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
876    
877      <img src="/uploads/project_covers/61538b1974d64c58bfffb876b92d2958.png"
878           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
879    
880  </div>
881  <div class="p-4">
882    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
883      Support manche aspirateur Dyson
884      
885    </h2>
886    
887    <div class="mt-3 flex flex-wrap gap-1.5">
888      
889      
890        <span class="text-xs px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300" title="FabLab">🏭 Mobilab 66</span>
891      
892    </div>
893    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
894      <span class="truncate">par Pierre</span>
895      <span class="flex items-center gap-2 shrink-0">
896        <span class="inline-flex items-center gap-1" title="J'aime">
897          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
898            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
899          </svg>
900          0
901        </span>
902        <span class="inline-flex items-center gap-1" title="Consultations">
903          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
904            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
905            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
906          </svg>
907          327
908        </span>
909        <span class="inline-flex items-center gap-1" title="Commentaires">
910          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
911            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
912          </svg>
913          0
914        </span>
915        <span>10/01/2025</span>
916      </span>
917    </div>
918  </div>
919</a>
920              </div>
921            
922          
923            
924              <div class="snap-start shrink-0 w-[85%] sm:w-[45%] lg:w-[31%]">
925                
926<a href="/projects/la-bouee"
927   class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
928  <div class="aspect-[16/10] bg-slate-100 dark:bg-slate-800 overflow-hidden">
929    
930      <img src="/uploads/project_covers/6f74dfaddfa44d7c8ee10256e6967564.png"
931           alt="" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300">
932    
933  </div>
934  <div class="p-4">
935    <h2 class="font-semibold text-slate-900 dark:text-white group-hover:text-brand-600 dark:group-hover:text-brand-400 line-clamp-2">
936      La bouée
937      
938    </h2>
939    
940    <div class="mt-3 flex flex-wrap gap-1.5">
941      
942      
943    </div>
944    <div class="mt-3 text-xs text-slate-500 dark:text-slate-500 flex items-center justify-between">
945      <span class="truncate">par Pierre</span>
946      <span class="flex items-center gap-2 shrink-0">
947        <span class="inline-flex items-center gap-1" title="J'aime">
948          <svg class="w-3.5 h-3.5" fill="currentColor" viewBox="0 0 24 24">
949            <path d="M12 21s-7-4.35-9.5-8.5C.7 9.4 2.6 5 6.5 5 8.6 5 10.4 6 12 7.5 13.6 6 15.4 5 17.5 5c3.9 0 5.8 4.4 4 7.5C19 16.65 12 21 12 21z"/>
950          </svg>
951          0
952        </span>
953        <span class="inline-flex items-center gap-1" title="Consultations">
954          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
955            <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"/>
956            <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
957          </svg>
958          338
959        </span>
960        <span class="inline-flex items-center gap-1" title="Commentaires">
961          <svg class="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75">
962            <path stroke-linecap="round" stroke-linejoin="round" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8-1.34 0-2.61-.26-3.76-.72L3 20l1.72-4.24C4.26 14.61 4 13.34 4 12c0-4.418 4.03-8 9-8s8 3.582 8 8z"/>
963          </svg>
964          0
965        </span>
966        <span>02/12/2024</span>
967      </span>
968    </div>
969  </div>
970</a>
971              </div>
972            
973          
974        </div>
975      </div>
976    </section>
977
978    
978<script>
979      (function () {
980        document.querySelectorAll('[data-carousel]').forEach(function (root) {
981          var track = root.querySelector('[data-carousel-track]');
982          var prev = root.querySelector('[data-carousel-prev]');
983          var next = root.querySelector('[data-carousel-next]');
984          if (!track) return;
985          function step() {
986            var first = track.querySelector(':scope > div');
987            return first ? first.getBoundingClientRect().width + 20 : track.clientWidth * 0.9;
988          }
989          if (prev) prev.addEventListener('click', function () { track.scrollBy({ left: -step(), behavior: 'smooth' }); });
990          if (next) next.addEventListener('click', function () { track.scrollBy({ left: step(), behavior: 'smooth' }); });
991        });
992      })();
993    </script>
993
994  
995
996  
997  
998    <section class="bg-slate-50 dark:bg-slate-950 border-y border-slate-200 dark:border-slate-800">
999      <div class="max-w-6xl mx-auto px-4 py-12">
1000        <div class="flex items-end justify-between mb-6 gap-3 flex-wrap">
1001          <div>
1002            <h2 class="text-2xl font-bold text-slate-900 dark:text-white">Communautés</h2>
1003            <p class="text-sm text-slate-500 dark:text-slate-400 mt-1">FabLabs, tiers-lieux et collectifs près de chez vous.</p>
1004          </div>
1005          <a href="/communities/"
1006             class="text-sm text-brand-600 dark:text-brand-400 hover:underline">Toutes les communautés →</a>
1007        </div>
1008        <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
1009          
1010            <a href="/communities/low-tech-lab-66"
1011               class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl p-4 shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
1012              <div class="flex items-center gap-3">
1013                
1014                  <img src="/uploads/communities/9b86689a2e23429288ca5ac637ef69e0.jpg"
1015                       alt="" class="w-12 h-12 rounded-lg object-cover">
1016                
1017                <div class="min-w-0 flex-1">
1018                  <div class="font-semibold text-slate-900 dark:text-white truncate group-hover:text-brand-600 dark:group-hover:text-brand-400">Low-Tech Lab 66</div>
1019                  <div class="text-xs text-slate-500 dark:text-slate-400">Association</div>
1020                </div>
1021              </div>
1022              
1023                <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">📍 133 chemin du Pas de la Paille, 66000 Perpignan</div>
1024              
1025              <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">
1026                0 projets
1027              </div>
1028            </a>
1029          
1030            <a href="/communities/la-cyber-fabrique"
1031               class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl p-4 shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
1032              <div class="flex items-center gap-3">
1033                
1034                  <img src="/uploads/communities/ce69554ac4de4b2fab5e4e14c44ffc8b.png"
1035                       alt="" class="w-12 h-12 rounded-lg object-cover">
1036                
1037                <div class="min-w-0 flex-1">
1038                  <div class="font-semibold text-slate-900 dark:text-white truncate group-hover:text-brand-600 dark:group-hover:text-brand-400">La Cyber Fabrique</div>
1039                  <div class="text-xs text-slate-500 dark:text-slate-400">FabLab</div>
1040                </div>
1041              </div>
1042              
1043                <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">📍 38 Route de Toulouges, 66270 Le Soler</div>
1044              
1045              <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">
1046                4 projets
1047              </div>
1048            </a>
1049          
1050            <a href="/communities/fablab-maillol"
1051               class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl p-4 shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
1052              <div class="flex items-center gap-3">
1053                
1054                  <img src="/uploads/communities/c7c9edd3b2964992a3f8715be79ce458.jpg"
1055                       alt="" class="w-12 h-12 rounded-lg object-cover">
1056                
1057                <div class="min-w-0 flex-1">
1058                  <div class="font-semibold text-slate-900 dark:text-white truncate group-hover:text-brand-600 dark:group-hover:text-brand-400">FabLab Maillol</div>
1059                  <div class="text-xs text-slate-500 dark:text-slate-400">FabLab</div>
1060                </div>
1061              </div>
1062              
1063                <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">📍 Perpignan</div>
1064              
1065              <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">
1066                5 projets
1067              </div>
1068            </a>
1069          
1070            <a href="/communities/mobilab-66"
1071               class="group block bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl p-4 shadow-sm hover:shadow-md hover:border-brand-300 dark:hover:border-brand-700 transition">
1072              <div class="flex items-center gap-3">
1073                
1074                  <img src="/uploads/communities/5a7148f36b484f81a9801271934410ca.jpg"
1075                       alt="" class="w-12 h-12 rounded-lg object-cover">
1076                
1077                <div class="min-w-0 flex-1">
1078                  <div class="font-semibold text-slate-900 dark:text-white truncate group-hover:text-brand-600 dark:group-hover:text-brand-400">Mobilab 66</div>
1079                  <div class="text-xs text-slate-500 dark:text-slate-400">FabLab</div>
1080                </div>
1081              </div>
1082              
1083                <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">📍 Perpignan</div>
1084              
1085              <div class="mt-2 text-xs text-slate-500 dark:text-slate-400">
1086                29 projets
1087              </div>
1088            </a>
1089          
1090        </div>
1091      </div>
1092    </section>
1093  
1094
1095  
1096  
1097
1098  
1099  
1100    <section class="max-w-6xl mx-auto px-4 py-12">
1101      <div class="flex items-end justify-between mb-6 gap-3 flex-wrap">
1102        <div>
1103          <h2 class="text-2xl font-bold text-slate-900 dark:text-white">Derniers messages</h2>
1104          <p class="text-sm text-slate-500 dark:text-slate-400 mt-1">Annonces, discussions et idées de la communauté makers.</p>
1105        </div>
1106        <a href="/posts/"
1107           class="text-sm text-brand-600 dark:text-brand-400 hover:underline">Voir le feed complet →</a>
1108      </div>
1109      <div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
1110        
1111          <div class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl overflow-hidden shadow-sm">
1112            
1113              <a href="/posts/2/">
1114                <img src="/uploads/post_images/d39a5be33b2546f2b3be71d5f5ef9631.jpg"
1115                     alt="" class="w-full h-36 object-cover">
1116              </a>
1117            
1118            <div class="p-4 flex flex-col gap-2">
1119              <div class="flex items-center gap-2">
1120                <a href="/u/fabien" class="shrink-0">
1121                  
1122                    <div class="w-7 h-7 rounded-full bg-slate-200 dark:bg-slate-700 grid place-items-center text-xs font-bold text-slate-500 dark:text-slate-300">
1123                      F
1124                    </div>
1125                  
1126                </a>
1127                <a href="/u/fabien"
1128                   class="text-sm font-medium text-slate-800 dark:text-slate-100 hover:text-brand-600 dark:hover:text-brand-400 truncate">
1129                  Fabien
1130                </a>
1131                
1132              </div>
1133              <a href="/posts/2/"
1134                 class="text-sm text-slate-700 dark:text-slate-300 line-clamp-3 hover:text-slate-900 dark:hover:text-white whitespace-pre-line">Lancement de la nouvelle plateforme FabLab66 pour fédérer tous les tiers-l
1134ieux du département, pour faire ensemble !
1135Vous pouvez utiliser ce Feed pour partager des news, des questions, des remarques, ...
1136Si vous souhaitez de nouvelles fonctionnalités, si vous rencontrez des bugs, n&#39;hésitez pas à commenter ce message.</a>
1137              <a href="/posts/2/#comments"
1138                 class="text-xs text-slate-400 dark:text-slate-500 hover:text-brand-600 dark:hover:text-brand-400">
1139                2 commentaires
1140              </a>
1141            </div>
1142          </div>
1143        
1144      </div>
1145    </section>
1146  
1147
1148  
1149  <section class="bg-slate-50 dark:bg-slate-950 border-t border-slate-200 dark:border-slate-800">
1150    <div class="max-w-5xl mx-auto px-4 py-14 grid gap-6 sm:grid-cols-3">
1151      
1152      <div class="bg-white rounded-2xl border border-slate-200 p-5 shadow-sm
1153                  dark:bg-slate-900 dark:border-slate-800">
1154        <div class="text-3xl">📐</div>
1155        <h3 class="mt-3 font-semibold text-slate-900 dark:text-white">Projets documentés</h3>
1156        <p class="mt-1 text-sm text-slate-600 dark:text-slate-400">Rédigez pas-à-pas avec photos, plans, fichiers CAO, code, PDF…</p>
1157      </div>
1158      
1159      <div class="bg-white rounded-2xl border border-slate-200 p-5 shadow-sm
1160                  dark:bg-slate-900 dark:border-slate-800">
1161        <div class="text-3xl">🛠️</div>
1162        <h3 class="mt-3 font-semibold text-slate-900 dark:text-white">Matériel partagé</h3>
1163        <p class="mt-1 text-sm text-slate-600 dark:text-slate-400">Proposez l&#39;accès à vos machines. Gratuit ou payant, à l&#39;heure ou à la journée.</p>
1164      </div>
1165      
1166      <div class="bg-white rounded-2xl border border-slate-200 p-5 shadow-sm
1167                  dark:bg-slate-900 dark:border-slate-800">
1168        <div class="text-3xl">🎓</div>
1169        <h3 class="mt-3 font-semibold text-slate-900 dark:text-white">Formations &amp; ateliers</h3>
1170        <p class="mt-1 text-sm text-slate-600 dark:text-slate-400">Trouvez ou proposez des sessions près de chez vous.</p>
1171      </div>
1172      
1173    </div>
1174  </section>
1175
1176  </main>
1177
1178  
1179  <div id="lightbox"
1180       class="hidden fixed inset-0 z-50 bg-black/90 items-center justify-center p-4 cursor-zoom-out"
1181       role="dialog" aria-modal="true" aria-label="Image en plein écran">
1182    <button type="button" id="lightbox-close"
1183            class="absolute top-4 right-4 text-white/80 hover:text-white text-3xl leading-none w-10 h-10 flex items-center justify-center rounded-full bg-black/40 hover:bg-black/60"
1184            aria-label="Fermer">&times;</button>
1185    <img id="lightbox-img" src="" alt=""
1186         class="max-w-[95vw] max-h-[95vh] object-contain rounded-lg shadow-2xl">
1187  </div>
1188
1189  <footer class="border-t border-slate-200 bg-white dark:bg-slate-900 dark:border-slate-800">
1190    <div class="max-w-5xl mx-auto px-4 py-6 text-sm text-slate-500 dark:text-slate-400 flex flex-col sm:flex-row justify-between gap-2">
1191      <div>© 2026 FabLab66 — Communauté des makers des Pyrénées-Orientales</div>
1192      <div class="flex gap-4">
1193        <a href="/mentions-legales" class="hover:text-brand-500">Mentions légales</a>
1194        <a href="/contact" class="hover:text-brand-500">Contact</a>
1195      </div>
1196    </div>
1197  </footer>
1198
1199  
1200  
1200<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cropper.min.js"></script>
1200
1201
1202  
1203  <div id="crop-modal"
1204       class="hidden fixed inset-0 z-[60] bg-black/80 flex items-center justify-center p-4"
1205       role="dialog" aria-modal="true" aria-label="Recadrer l'image">
1206    <div class="bg-white dark:bg-slate-900 rounded-2xl shadow-2xl w-full max-w-2xl p-5 space-y-4">
1207      <div class="flex items-center justify-between">
1208        <h3 class="font-semibold text-slate-900 dark:text-white">Recadrer l'image</h3>
1209        <button id="crop-cancel" type="button"
1210                class="text-slate-400 hover:text-slate-600 dark:hover:text-slate-300 p-1 rounded"
1211                aria-label="Annuler">
1212          <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
1213            <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
1214          </svg>
1215        </button>
1216      </div>
1217      <div class="rounded-lg overflow-hidden bg-slate-100 dark:bg-slate-800 max-h-[55vh]">
1218        <img id="crop-image" src="" alt="" style="display:block;max-width:100%">
1219      </div>
1220      <p class="text-xs text-slate-500 dark:text-slate-400">Déplacez et redimensionnez la zone pour choisir le cadrage.</p>
1221      <div class="flex flex-wrap items-center gap-3">
1222        <span class="text-xs text-slate-500 dark:text-slate-400 shrink-0">Fond :</span>
1223        <div class="flex items-center gap-1.5" id="crop-bg-presets">
1224          <button type="button" data-bg="transparent"
1225                  class="crop-bg-btn w-6 h-6 rounded border-2 border-brand-500 ring-1 ring-brand-400"
1226                  style="background:repeating-conic-gradient(#ccc 0% 25%,#fff 0% 50%) 0 0/8px 8px"
1227                  title="Transparent"></button>
1228          <button type="button" data-bg="#ffffff"
1229                  class="crop-bg-btn w-6 h-6 rounded border-2 border-transparent hover:border-slate-400"
1230                  style="background:#ffffff" title="Blanc"></button>
1231          <button type="button" data-bg="#000000"
1232                  class="crop-bg-btn w-6 h-6 rounded border-2 border-transparent hover:border-slate-400"
1233                  style="background:#000000" title="Noir"></button>
1234          <button type="button" data-bg="#f1f5f9"
1235                  class="crop-bg-btn w-6 h-6 rounded border-2 border-transparent hover:border-slate-400"
1236                  style="background:#f1f5f9" title="Gris clair"></button>
1237          <label class="w-6 h-6 rounded border-2 border-transparent hover:border-slate-400 overflow-hidden cursor-pointer" title="Couleur personnalisée">
1238            <input type="color" id="crop-bg-custom" value="#ffffff"
1239                   class="w-8 h-8 -mt-1 -ml-1 cursor-pointer opacity-0 absolute">
1240            <div id="crop-bg-custom-swatch" class="w-full h-full" style="background:linear-gradient(135deg,red,yellow,lime,cyan,blue,magenta)"></div>
1241          </label>
1242        </div>
1243        <div class="flex gap-3 ml-auto">
1244          <button id="crop-cancel-btn" type="button"
1245                  class="px-4 py-2 text-sm rounded-lg border border-slate-300 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-800 text-slate-700 dark:text-slate-300">
1246            Annuler
1247          </button>
1248          <button id="crop-confirm" type="button"
1249                  class="px-5 py-2 text-sm rounded-lg bg-brand-500 hover:bg-brand-600 text-white font-medium">
1250            Valider le recadrage
1251          </button>
1252        </div>
1253      </div>
1254    </div>
1255  </div>
1256
1257  
1257<script>
1258    // Theme toggle
1259    (function () {
1260      var root = document.documentElement;
1261      function apply(theme) {
1262        if (theme === 'dark') root.classList.add('dark');
1263        else root.classList.remove('dark');
1264      }
1265      window.__setTheme = function (mode) {
1266        // mode = 'light' | 'dark' | 'system'
1267        if (mode === 'system') {
1268          localStorage.removeItem('theme');
1269          apply(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
1270        } else {
1271          localStorage.setItem('theme', mode);
1272          apply(mode);
1273        }
1274      };
1275      window.__toggleTheme = function () {
1276        var isDark = root.classList.contains('dark');
1277        window.__setTheme(isDark ? 'light' : 'dark');
1278      };
1279      // Follow system changes only when user hasn't chosen manually
1280      window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {
1281        if (localStorage.getItem('theme') === null) apply(e.matches ? 'dark' : 'light');
1282      });
1283    })();
1284  </script>
1284
1285
1286  
1286<script>
1287    // Image cropper — activated on <input type="file" data-crop="RATIO">
1288    // RATIO: "1" = square, "1.778" = 16/9, absent/empty = free
1289    (function () {
1290      var modal   = document.getElementById('crop-modal');
1291      var imgEl   = document.getElementById('crop-image');
1292      var confirmBtn = document.getElementById('crop-confirm');
1293      var cancelBtns = [document.getElementById('crop-cancel'), document.getElementById('crop-cancel-btn')];
1294      if (!modal || !imgEl) return;
1295
1296      var cropper = null;
1297      var targetInput = null;
1298      var originalFile = null;
1299      var bgColor = 'transparent';
1300
1301      // Background color presets
1302      var bgBtns = document.querySelectorAll('.crop-bg-btn');
1303      var customPicker = document.getElementById('crop-bg-custom');
1304      var customSwatch = document.getElementById('crop-bg-custom-swatch');
1305
1306      function selectBg(color, activateBtn) {
1307        bgColor = color;
1308        bgBtns.forEach(function (b) { b.classList.remove('border-brand-500', 'ring-1', 'ring-brand-400'); b.classList.add('border-transparent'); });
1309        if (activateBtn) { activateBtn.classList.remove('border-transparent'); activateBtn.classList.add('border-brand-500', 'ring-1', 'ring-brand-400'); }
1310      }
1311
1312      bgBtns.forEach(function (btn) {
1313        btn.addEventListener('click', function () { selectBg(btn.dataset.bg, btn); });
1314      });
1315      if (customPicker) {
1316        customPicker.addEventListener('input', function () {
1317          var color = customPicker.value;
1318          customSwatch.style.background = color;
1319          selectBg(color, null);
1320        });
1321      }
1322
1323      function openCropper(input, file) {
1324        targetInput = input;
1325        originalFile = file;
1326        var reader = new FileReader();
1327        reader.onload = function (e) {
1328          if (cropper) { cropper.destroy(); cropper = null; }
1329          imgEl.src = e.target.result;
1330          modal.classList.remove('hidden');
1331          document.body.style.overflow = 'hidden';
1332          var ratioStr = input.dataset.crop;
1333          var ratio = parseFloat(ratioStr);
1334          cropper = new Cropper(imgEl, {
1335            aspectRatio: (ratioStr && !isNaN(ratio)) ? ratio : NaN,
1336            viewMode: 1,
1337            autoCropArea: 0.9,
1338            responsive: true,
1339            guides: true,
1340            center: true,
1341            highlight: false,
1342          });
1343        };
1344        reader.readAsDataURL(file);
1345      }
1346
1347      function closeCropper(clearInput) {
1348        modal.classList.add('hidden');
1349        document.body.style.overflow = '';
1350        if (cropper) { cropper.destroy(); cropper = null; }
1351        imgEl.src = '';
1352        if (clearInput && targetInput) targetInput.value = '';
1353        targetInput = null;
1354        originalFile = null;
1355      }
1356
1357      cancelBtns.forEach(function (btn) {
1358        if (btn) btn.addEventListener('click', function () { closeCropper(true); });
1359      });
1360
1361      confirmBtn.addEventListener('click', function () {
1362        if (!cropper || !targetInput) return;
1363        var isPng = (originalFile && originalFile.type === 'image/png') && bgColor === 'transparent';
1364        var mime = isPng ? 'image/png' : 'image/jpeg';
1365        var ext  = isPng ? 'png' : 'jpg';
1366        var canvasOpts = { maxWidth: 2048, maxHeight: 2048, imageSmoothingEnabled: true, imageSmoothingQuality: 'high' };
1367        if (bgColor && bgColor !== 'transparent') canvasOpts.fillColor = bgColor;
1368        var canvas = cropper.getCroppedCanvas(canvasOpts);
1369        canvas.toBlob(function (blob) {
1370          var newFile = new File([blob], 'crop.' + ext, { type: mime });
1371          try {
1372            var dt = new DataTransfer();
1373            dt.items.add(newFile);
1374            targetInput.files = dt.files;
1375          } catch (_) {
1376            // DataTransfer not supported — fallback: keep original file
1377          }
1378          closeCropper(false);
1379        }, mime, 0.92);
1380      });
1381
1382      // Watch ALL file inputs (present + future via delegation)
1383      document.addEventListener('change', function (e) {
1384        var input = e.target;
1385        if (!input || input.tagName !== 'INPUT' || input.type !== 'file') return;
1386        if (!('crop' in input.dataset)) return;
1387        if (!input.files || !input.files[0]) return;
1388        if (!window.Cropper) return;
1389        var file = input.files[0];
1390        if (!file.type.startsWith('image/')) return;
1391        openCropper(input, file);
1392      });
1393    })();
1394  </script>
1394
1395
1396  
1396<script>
1397    // Syntax highlighting for markdown code blocks.
1398    window.addEventListener('DOMContentLoaded', function () {
1399      if (window.hljs) {
1400        document.querySelectorAll('.prose pre code').forEach(function (el) {
1401          try { window.hljs.highlightElement(el); } catch (_) {}
1402        });
1403      }
1404    });
1405
1406    // Voice dictation — Web Speech API on <textarea data-voice="1">
1407    (function () {
1408      var SR = window.SpeechRecognition || window.webkitSpeechRecognition;
1409      if (!SR) return;
1410
1411      function attach(ta) {
1412        if (ta.dataset.voiceReady) return;
1413        ta.dataset.voiceReady = '1';
1414
1415        var wrapper = document.createElement('div');
1416        wrapper.className = 'relative';
1417        ta.parentNode.insertBefore(wrapper, ta);
1418        wrapper.appendChild(ta);
1419
1420        var btn = document.createElement('button');
1421        btn.type = 'button';
1422        btn.setAttribute('aria-label', 'Dictée vocale');
1423        btn.title = 'Dictée vocale (cliquer pour démarrer / arrêter)';
1424        btn.className = 'absolute top-2 right-2 z-10 w-8 h-8 rounded-full bg-white/90 dark:bg-slate-800/90 border border-slate-300 dark:border-slate-600 shadow-sm hover:bg-brand-50 dark:hover:bg-slate-700 text-slate-500 dark:text-slate-300 flex items-center justify-center transition';
1425        btn.innerHTML = '<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.75"><path stroke-linecap="round" stroke-linejoin="round" d="M12 18.75a6 6 0 006-6v-1.5m-6 7.5a6 6 0 01-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 01-3-3V4.5a3 3 0 116 0v8.25a3 3 0 01-3 3z"/></svg>';
1426        wrapper.appendChild(btn);
1427
1428        var rec = null;
1429        var active = false;
1430
1431        function insertText(text) {
1432          if (!text) return;
1433          var start = ta.selectionStart || ta.value.length;
1434          var end = ta.selectionEnd || ta.value.length;
1435          var before = ta.value.slice(0, start);
1436          var after = ta.value.slice(end);
1437          var sep = (before && !/\s$/.test(before)) ? ' ' : '';
1438          ta.value = before + sep + text + after;
1439          var pos = (before + sep + text).length;
1440          ta.setSelectionRange(pos, pos);
1441          ta.dispatchEvent(new Event('input', { bubbles: true }));
1442        }
1443
1444        function stop() {
1445          if (rec) { try { rec.stop(); } catch (_) {} }
1446          active = false;
1447          btn.classList.remove('bg-red-500', 'text-white', 'animate-pulse');
1448          btn.classList.add('bg-white/90', 'dark:bg-slate-800/90', 'text-slate-500', 'dark:text-slate-300');
1449        }
1450
1451        function start() {
1452          try {
1453            rec = new SR();
1454            rec.lang = document.documentElement.lang || 'fr-FR';
1455            if (rec.lang.length === 2) rec.lang = rec.lang + '-FR';
1456            rec.continuous = true;
1457            rec.interimResults = false;
1458            rec.onresult = function (e) {
1459              var chunk = '';
1460              for (var i = e.resultIndex; i < e.results.length; i++) {
1461                if (e.results[i].isFinal) chunk += e.results[i][0].transcript;
1462              }
1463              if (chunk) insertText(chunk.trim());
1464            };
1465            rec.onerror = function () { stop(); };
1466            rec.onend = function () { if (active) { try { rec.start(); } catch (_) { stop(); } } };
1467            rec.start();
1468            active = true;
1469            btn.classList.remove('bg-white/90', 'dark:bg-slate-800/90', 'text-slate-500', 'dark:text-slate-300');
1470            btn.classList.add('bg-red-500', 'text-white', 'animate-pulse');
1471          } catch (_) { stop(); }
1472        }
1473
1474        btn.addEventListener('click', function () {
1475          if (active) stop(); else start();
1476        });
1477      }
1478
1479      function scan(root) {
1480        (root || document).querySelectorAll('textarea[data-voice="1"]').forEach(attach);
1481      }
1482      window.addEventListener('DOMContentLoaded', function () { scan(document); });
1483      document.addEventListener('htmx:afterSwap', function (e) { scan(e.target); });
1484    })();
1485
1486    // In-page image lightbox.
1487    (function () {
1488      var box = document.getElementById('lightbox');
1489      var img = document.getElementById('lightbox-img');
1490      var closer = document.getElementById('lightbox-close');
1491      if (!box || !img) return;
1492
1493      function open(src, alt) {
1494        img.src = src;
1495        img.alt = alt || '';
1496        box.classList.remove('hidden');
1497        box.classList.add('flex');
1498        document.body.style.overflow = 'hidden';
1499      }
1500      function close() {
1501        box.classList.add('hidden');
1502        box.classList.remove('flex');
1503        img.src = '';
1504        document.body.style.overflow = '';
1505      }
1506
1507      // Any image marked data-lightbox, plus any <img> inside a .prose block,
1508      // opens the overlay instead of navigating away.
1509      document.addEventListener('click', function (e) {
1510        var el = e.target;
1511        if (!el) return;
1512
1513        // Trigger by wrapping anchor with data-lightbox-src
1514        var trigger = el.closest && el.closest('[data-lightbox-src]');
1515        if (trigger) {
1516          e.preventDefault();
1517          open(trigger.getAttribute('data-lightbox-src'), trigger.getAttribute('data-lightbox-alt'));
1518          return;
1519        }
1520
1521        // Trigger by clicking any img inside a .prose block
1522        if (el.tagName === 'IMG' && el.closest('.prose')) {
1523          e.preventDefault();
1524          open(el.currentSrc || el.src, el.alt);
1525          return;
1526        }
1527      });
1528
1529      box.addEventListener('click', function (e) {
1530        if (e.target === box || e.target === closer) close();
1531      });
1532      document.addEventListener('keydown', function (e) {
1533        if (e.key === 'Escape' && !box.classList.contains('hidden')) close();
1534      });
1535    })();
1536  </script>
1536
1537  
1538</body>
1539</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.