Dimdam's
Dimdam’s Git

dimdams / dimdams-docs

Documentation de Dimdams

Public
00

design: refonte moderne de la documentation et de la landing page selon la charte Dimdam's

Benladamm · il y a 8 he6f569061ca2 parent 3d72b96Parcourir les fichiers à ce commit

5 fichiers modifiés · +990 −136

ModifiéREADME.md+1−0
@@ -30,3 +30,4 @@ npm run build
3030 # Déploiement sur server-003
3131 npm run deploy
3232 ```
33+
Modifiéscripts/check-content.mjs+1−0
@@ -100,3 +100,4 @@ if (errors > 0) {
100100 } else {
101101 console.log("✅ Contenu valide !");
102102 }
103+
Modifiésrc/app/globals.css+772−116
@@ -1,186 +1,839 @@
1−/* Dimdam's Docs: Dimdam's colors, dark and light theme (data-theme on <html>, otherwise the system's). */
1+/* Dimdam's Docs: Design System Dimdam's, Dark & Light theme */
22
33 :root {
4− --canvas: #09090b; --surface: #141417; --surface-2: #0f0f12; --line: rgba(255, 255, 255, 0.08); --line-2: rgba(255, 255, 255, 0.14);
5− --text: #d9dce1; --muted: #9ca3af; --faint: #6b7280; --strong: #fff;
6− --accent: #6b2030; --accent-hover: #561a26; --accent-light: #d0566e; --accent-soft: #f3b4c1;
7− --note: #38bdf8; --note-soft: rgba(56, 189, 248, 0.1); --tip: #22c55e; --tip-soft: rgba(34, 197, 94, 0.1);
8− --warn: #f59e0b; --warn-soft: rgba(245, 158, 11, 0.1); --danger: #f43f5e; --danger-soft: rgba(244, 63, 94, 0.1);
9− --code-bg: #0d0d10; --inline-code: rgba(255, 255, 255, 0.07);
4+ --canvas: #07070a;
5+ --surface: #0d0d12;
6+ --surface-2: #121218;
7+ --line: rgba(255, 255, 255, 0.08);
8+ --line-2: rgba(255, 255, 255, 0.14);
9+ --text: #d9dce1;
10+ --muted: #9ca3af;
11+ --faint: #6b7280;
12+ --strong: #ffffff;
13+ --accent: #6b2030;
14+ --accent-hover: #561a26;
15+ --accent-light: #e05d76;
16+ --accent-soft: #f3b4c1;
17+ --accent-glow: rgba(107, 32, 48, 0.28);
18+ --note: #38bdf8;
19+ --note-soft: rgba(56, 189, 248, 0.1);
20+ --tip: #22c55e;
21+ --tip-soft: rgba(34, 197, 94, 0.1);
22+ --warn: #f59e0b;
23+ --warn-soft: rgba(245, 158, 11, 0.1);
24+ --danger: #f43f5e;
25+ --danger-soft: rgba(244, 63, 94, 0.1);
26+ --code-bg: #09090d;
27+ --inline-code: rgba(255, 255, 255, 0.07);
1028 color-scheme: dark;
1129 }
30+
1231 :root[data-theme="light"] {
13− --canvas: #f7f7f8; --surface: #fff; --surface-2: #f1f1f3; --line: rgba(0, 0, 0, 0.08); --line-2: rgba(0, 0, 0, 0.14);
14− --text: #2b2f36; --muted: #4b5563; --faint: #8b93a1; --strong: #111827;
15− --accent-light: #a3283f; --accent-soft: #6b2030;
16− --note: #0284c7; --note-soft: rgba(2, 132, 199, 0.08); --tip: #15803d; --tip-soft: rgba(21, 128, 61, 0.08);
17− --warn: #b45309; --warn-soft: rgba(217, 119, 6, 0.1); --danger: #be123c; --danger-soft: rgba(225, 29, 72, 0.08);
18− --code-bg: #f6f6f8; --inline-code: rgba(0, 0, 0, 0.06);
32+ --canvas: #f8f9fa;
33+ --surface: #ffffff;
34+ --surface-2: #f1f3f5;
35+ --line: rgba(0, 0, 0, 0.08);
36+ --line-2: rgba(0, 0, 0, 0.14);
37+ --text: #2b2f36;
38+ --muted: #4b5563;
39+ --faint: #8b93a1;
40+ --strong: #111827;
41+ --accent-light: #a3283f;
42+ --accent-soft: #6b2030;
43+ --accent-glow: rgba(107, 32, 48, 0.08);
44+ --note: #0284c7;
45+ --note-soft: rgba(2, 132, 199, 0.08);
46+ --tip: #15803d;
47+ --tip-soft: rgba(21, 128, 61, 0.08);
48+ --warn: #b45309;
49+ --warn-soft: rgba(217, 119, 6, 0.1);
50+ --danger: #be123c;
51+ --danger-soft: rgba(225, 29, 72, 0.08);
52+ --code-bg: #f3f4f6;
53+ --inline-code: rgba(0, 0, 0, 0.06);
1954 color-scheme: light;
2055 }
56+
2157 @media (prefers-color-scheme: light) {
2258 :root:not([data-theme]) {
23− --canvas: #f7f7f8; --surface: #fff; --surface-2: #f1f1f3; --line: rgba(0, 0, 0, 0.08); --line-2: rgba(0, 0, 0, 0.14);
24− --text: #2b2f36; --muted: #4b5563; --faint: #8b93a1; --strong: #111827;
25− --accent-light: #a3283f; --accent-soft: #6b2030;
26− --note: #0284c7; --note-soft: rgba(2, 132, 199, 0.08); --tip: #15803d; --tip-soft: rgba(21, 128, 61, 0.08);
27− --warn: #b45309; --warn-soft: rgba(217, 119, 6, 0.1); --danger: #be123c; --danger-soft: rgba(225, 29, 72, 0.08);
28− --code-bg: #f6f6f8; --inline-code: rgba(0, 0, 0, 0.06);
59+ --canvas: #f8f9fa;
60+ --surface: #ffffff;
61+ --surface-2: #f1f3f5;
62+ --line: rgba(0, 0, 0, 0.08);
63+ --line-2: rgba(0, 0, 0, 0.14);
64+ --text: #2b2f36;
65+ --muted: #4b5563;
66+ --faint: #8b93a1;
67+ --strong: #111827;
68+ --accent-light: #a3283f;
69+ --accent-soft: #6b2030;
70+ --accent-glow: rgba(107, 32, 48, 0.08);
71+ --note: #0284c7;
72+ --note-soft: rgba(2, 132, 199, 0.08);
73+ --tip: #15803d;
74+ --tip-soft: rgba(21, 128, 61, 0.08);
75+ --warn: #b45309;
76+ --warn-soft: rgba(217, 119, 6, 0.1);
77+ --danger: #be123c;
78+ --danger-soft: rgba(225, 29, 72, 0.08);
79+ --code-bg: #f3f4f6;
80+ --inline-code: rgba(0, 0, 0, 0.06);
2981 color-scheme: light;
3082 }
3183 }
3284
3385 * { box-sizing: border-box; }
3486 html { scroll-padding-top: 88px; }
35−body { margin: 0; min-height: 100vh; display: flex; flex-direction: column; background: var(--canvas); color: var(--text); font-family: var(--font-inter), system-ui, sans-serif; font-size: 16px; line-height: 1.65; -webkit-font-smoothing: antialiased; }
36−a { color: var(--accent-light); }
37−h1, h2, h3, h4 { font-family: var(--font-outfit), system-ui, sans-serif; color: var(--strong); line-height: 1.25; }
87+body {
88+ margin: 0;
89+ min-height: 100vh;
90+ display: flex;
91+ flex-direction: column;
92+ background: var(--canvas);
93+ color: var(--text);
94+ font-family: var(--font-inter), system-ui, sans-serif;
95+ font-size: 15px;
96+ line-height: 1.65;
97+ -webkit-font-smoothing: antialiased;
98+}
99+
100+a { color: var(--accent-light); text-decoration: none; }
101+h1, h2, h3, h4 {
102+ font-family: var(--font-outfit), system-ui, sans-serif;
103+ color: var(--strong);
104+ line-height: 1.25;
105+}
38106 code, kbd, pre { font-family: var(--font-mono), ui-monospace, monospace; }
39107 :focus-visible { outline: 2px solid var(--accent-light); outline-offset: 2px; border-radius: 4px; }
40108
41109 /* Buttons */
42−.btn { font: inherit; font-size: 13px; font-weight: 600; padding: 8px 14px; border-radius: 10px; border: 1px solid var(--line-2); background: var(--surface); color: var(--text); cursor: pointer; text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }
43−.btn:hover { border-color: var(--faint); }
44−.btn.primary { background: var(--accent); border-color: #c2415a; color: #fff; }
45−.btn.primary:hover { background: var(--accent-hover); }
110+.btn {
111+ font: inherit;
112+ font-size: 13px;
113+ font-weight: 600;
114+ padding: 8px 16px;
115+ border-radius: 10px;
116+ border: 1px solid var(--line-2);
117+ background: var(--surface);
118+ color: var(--text);
119+ cursor: pointer;
120+ text-decoration: none;
121+ display: inline-flex;
122+ align-items: center;
123+ gap: 6px;
124+ transition: all 0.15s ease;
125+}
126+.btn:hover { border-color: var(--faint); color: var(--strong); }
127+.btn.primary {
128+ background: var(--accent);
129+ border-color: #8b263e;
130+ color: #fff;
131+ box-shadow: 0 4px 14px rgba(107, 32, 48, 0.35);
132+}
133+.btn.primary:hover {
134+ background: var(--accent-hover);
135+ border-color: #a3283f;
136+ transform: translateY(-1px);
137+}
46138 .btn.icon { padding: 8px; }
47139
48140 /* Header */
49−.header { position: sticky; top: 0; z-index: 40; border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--canvas) 85%, transparent); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); }
50−.header-in { max-width: 1360px; margin: 0 auto; padding: 0 20px; height: 64px; display: flex; align-items: center; gap: 20px; }
51−.brand { display: flex; align-items: center; gap: 10px; font-family: var(--font-outfit), sans-serif; font-weight: 800; font-size: 18px; color: var(--strong); text-decoration: none; flex: none; }
52−.brand img { width: 36px; height: 36px; object-fit: contain; }
53−.tag { font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--line-2); color: var(--accent-soft); }
54−.tabs { display: flex; gap: 2px; font-size: 14px; }
55−.tabs a { padding: 7px 12px; border-radius: 10px; color: var(--muted); text-decoration: none; white-space: nowrap; }
56−.tabs a:hover, .tabs a[aria-current="page"] { color: var(--strong); background: var(--surface); }
57−.tabs a[aria-current="page"] { box-shadow: inset 0 -2px 0 var(--accent-light); }
141+.header {
142+ position: sticky;
143+ top: 0;
144+ z-index: 40;
145+ border-bottom: 1px solid var(--line);
146+ background: color-mix(in srgb, var(--canvas) 85%, transparent);
147+ backdrop-filter: blur(14px);
148+ -webkit-backdrop-filter: blur(14px);
149+}
150+.header-in {
151+ max-width: 1360px;
152+ margin: 0 auto;
153+ padding: 0 24px;
154+ height: 64px;
155+ display: flex;
156+ align-items: center;
157+ gap: 20px;
158+}
159+.brand {
160+ display: flex;
161+ align-items: center;
162+ gap: 10px;
163+ font-family: var(--font-outfit), sans-serif;
164+ font-weight: 800;
165+ font-size: 18px;
166+ color: var(--strong);
167+ text-decoration: none;
168+ flex: none;
169+}
170+.brand img { width: 34px; height: 34px; object-fit: contain; }
171+.tag {
172+ font-size: 10px;
173+ font-weight: 700;
174+ letter-spacing: 0.08em;
175+ text-transform: uppercase;
176+ padding: 3px 8px;
177+ border-radius: 999px;
178+ border: 1px solid var(--line-2);
179+ background: var(--surface-2);
180+ color: var(--accent-soft);
181+}
182+.tabs { display: flex; gap: 4px; font-size: 14px; }
183+.tabs a {
184+ padding: 6px 14px;
185+ border-radius: 9px;
186+ color: var(--muted);
187+ text-decoration: none;
188+ white-space: nowrap;
189+ font-weight: 500;
190+ transition: all 0.15s ease;
191+}
192+.tabs a:hover { color: var(--strong); background: var(--surface); }
193+.tabs a[aria-current="page"] {
194+ color: var(--strong);
195+ background: var(--surface);
196+ border: 1px solid var(--line);
197+ box-shadow: inset 0 -2px 0 var(--accent-light);
198+}
58199 .tabs-mobile { display: none; }
59−.header-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
60−.search-button { font: inherit; font-size: 13px; display: inline-flex; align-items: center; gap: 8px; padding: 7px 10px; min-width: 210px; border-radius: 10px; border: 1px solid var(--line-2); background: var(--surface-2); color: var(--faint); cursor: pointer; }
200+.header-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
201+.search-button {
202+ font: inherit;
203+ font-size: 13px;
204+ display: inline-flex;
205+ align-items: center;
206+ gap: 8px;
207+ padding: 7px 12px;
208+ min-width: 220px;
209+ border-radius: 10px;
210+ border: 1px solid var(--line);
211+ background: var(--surface-2);
212+ color: var(--faint);
213+ cursor: pointer;
214+ transition: border-color 0.15s;
215+}
61216 .search-button:hover { border-color: var(--faint); color: var(--muted); }
62217 .search-button kbd { margin-left: auto; }
63−kbd { font-size: 11px; padding: 1px 6px; border-radius: 6px; border: 1px solid var(--line-2); background: var(--surface); color: var(--muted); }
218+kbd {
219+ font-size: 11px;
220+ padding: 2px 6px;
221+ border-radius: 6px;
222+ border: 1px solid var(--line-2);
223+ background: var(--surface);
224+ color: var(--muted);
225+}
64226
65−/* Search */
66−.search-overlay { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, 0.55); backdrop-filter: blur(3px); display: flex; justify-content: center; padding: 10vh 16px 16px; }
67−.search-box { width: 100%; max-width: 640px; max-height: 75vh; display: flex; flex-direction: column; border-radius: 16px; border: 1px solid var(--line-2); background: var(--surface); box-shadow: 0 30px 80px rgba(0, 0, 0, 0.45); overflow: hidden; }
68−.search-box input { font: inherit; font-size: 16px; padding: 16px 18px; border: 0; border-bottom: 1px solid var(--line); background: transparent; color: var(--strong); outline: none; }
69−.search-results { list-style: none; margin: 0; padding: 6px; overflow-y: auto; }
70−.search-results button { width: 100%; text-align: left; font: inherit; display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; border-radius: 10px; border: 0; background: transparent; color: var(--text); cursor: pointer; }
71−.search-results button.active { background: var(--surface-2); box-shadow: inset 2px 0 0 var(--accent-light); }
227+/* Search Modal */
228+.search-overlay {
229+ position: fixed;
230+ inset: 0;
231+ z-index: 60;
232+ background: rgba(0, 0, 0, 0.7);
233+ backdrop-filter: blur(8px);
234+ display: flex;
235+ justify-content: center;
236+ padding: 10vh 16px 16px;
237+}
238+.search-box {
239+ width: 100%;
240+ max-width: 640px;
241+ max-height: 75vh;
242+ display: flex;
243+ flex-direction: column;
244+ border-radius: 18px;
245+ border: 1px solid var(--line-2);
246+ background: var(--surface);
247+ box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
248+ overflow: hidden;
249+}
250+.search-box input {
251+ font: inherit;
252+ font-size: 16px;
253+ padding: 16px 20px;
254+ border: 0;
255+ border-bottom: 1px solid var(--line);
256+ background: transparent;
257+ color: var(--strong);
258+ outline: none;
259+}
260+.search-results { list-style: none; margin: 0; padding: 8px; overflow-y: auto; }
261+.search-results button {
262+ width: 100%;
263+ text-align: left;
264+ font: inherit;
265+ display: flex;
266+ flex-direction: column;
267+ gap: 2px;
268+ padding: 10px 14px;
269+ border-radius: 10px;
270+ border: 0;
271+ background: transparent;
272+ color: var(--text);
273+ cursor: pointer;
274+ transition: background 0.15s;
275+}
276+.search-results button.active,
277+.search-results button:hover {
278+ background: var(--surface-2);
279+ box-shadow: inset 2px 0 0 var(--accent-light);
280+}
72281 .search-where { font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--faint); }
73282 .search-title { font-weight: 600; color: var(--strong); }
74283 .search-heading { font-weight: 500; color: var(--muted); }
75284 .search-snippet { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76−.search-empty { padding: 14px 12px; color: var(--muted); font-size: 14px; }
77−.search-help { margin: 0; padding: 10px 16px; border-top: 1px solid var(--line); font-size: 12px; color: var(--faint); }
285+.search-empty { padding: 18px; color: var(--muted); font-size: 14px; text-align: center; }
286+.search-help { margin: 0; padding: 10px 18px; border-top: 1px solid var(--line); font-size: 12px; color: var(--faint); }
78287
79−/* Home */
80−.home { max-width: 1160px; margin: 0 auto; padding: 56px 20px 72px; width: 100%; flex: 1; }
81−.hero { text-align: center; margin-bottom: 44px; }
82−.hero h1 { font-size: clamp(30px, 5vw, 44px); margin: 0 0 12px; letter-spacing: -0.02em; }
83−.hero p { max-width: 640px; margin: 0 auto; color: var(--muted); font-size: 17px; }
84−.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; }
85−.card { display: flex; flex-direction: column; padding: 22px; border-radius: 16px; border: 1px solid var(--line); background: var(--surface); text-decoration: none; color: var(--text); transition: border-color 0.15s, transform 0.15s; }
86−.card:hover { border-color: color-mix(in srgb, var(--accent-light) 45%, transparent); transform: translateY(-2px); }
87−.card h2 { margin: 0 0 6px; font-size: 19px; }
88−.card p { margin: 0 0 14px; color: var(--muted); font-size: 14px; }
89−.card ul { margin: 0 0 14px; padding-left: 18px; font-size: 14px; color: var(--muted); }
90−.card-more { margin-top: auto; font-size: 13px; font-weight: 600; color: var(--accent-light); }
288+/* Home / Landing Page */
289+.home {
290+ max-width: 1240px;
291+ margin: 0 auto;
292+ padding: 64px 24px 96px;
293+ width: 100%;
294+ flex: 1;
295+ position: relative;
296+}
297+
298+.home::before {
299+ content: "";
300+ position: absolute;
301+ top: 0;
302+ left: 50%;
303+ transform: translateX(-50%);
304+ width: 900px;
305+ height: 400px;
306+ background: radial-gradient(ellipse 60% 50% at 50% 0%, var(--accent-glow), transparent 70%);
307+ pointer-events: none;
308+ z-index: -1;
309+}
310+
311+.hero {
312+ text-align: center;
313+ margin-bottom: 56px;
314+ display: flex;
315+ flex-direction: column;
316+ align-items: center;
317+}
318+.hero-badge {
319+ display: inline-flex;
320+ align-items: center;
321+ gap: 8px;
322+ padding: 5px 14px;
323+ border-radius: 999px;
324+ border: 1px solid var(--line-2);
325+ background: var(--surface-2);
326+ font-size: 12px;
327+ font-weight: 600;
328+ color: var(--muted);
329+ margin-bottom: 20px;
330+}
331+.live-dot {
332+ width: 7px;
333+ height: 7px;
334+ border-radius: 999px;
335+ background: #22c55e;
336+ box-shadow: 0 0 10px #22c55e;
337+}
338+.hero h1 {
339+ font-size: clamp(32px, 5vw, 50px);
340+ font-weight: 800;
341+ margin: 0 0 16px;
342+ letter-spacing: -0.025em;
343+ color: var(--strong);
344+}
345+.hero p {
346+ max-width: 680px;
347+ margin: 0 auto;
348+ color: var(--muted);
349+ font-size: 17px;
350+ line-height: 1.6;
351+}
352+
353+.section-label {
354+ display: flex;
355+ align-items: center;
356+ gap: 8px;
357+ font-size: 12px;
358+ font-weight: 700;
359+ text-transform: uppercase;
360+ letter-spacing: 0.08em;
361+ color: var(--faint);
362+ margin-bottom: 18px;
363+}
364+
365+/* Cards Section */
366+.cards-section { margin-bottom: 56px; }
367+.cards {
368+ display: grid;
369+ grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
370+ gap: 20px;
371+}
372+.card {
373+ display: flex;
374+ flex-direction: column;
375+ padding: 26px;
376+ border-radius: 18px;
377+ border: 1px solid var(--line);
378+ background: var(--surface);
379+ text-decoration: none;
380+ color: var(--text);
381+ position: relative;
382+ transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
383+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
384+}
385+.card:hover {
386+ border-color: rgba(224, 93, 118, 0.4);
387+ transform: translateY(-3px);
388+ box-shadow: 0 12px 30px rgba(107, 32, 48, 0.2);
389+}
390+.card-header {
391+ display: flex;
392+ align-items: center;
393+ justify-content: space-between;
394+ margin-bottom: 16px;
395+}
396+.card-icon {
397+ width: 44px;
398+ height: 44px;
399+ border-radius: 12px;
400+ background: rgba(107, 32, 48, 0.18);
401+ border: 1px solid rgba(107, 32, 48, 0.35);
402+ color: #f3b4c1;
403+ display: flex;
404+ align-items: center;
405+ justify-content: center;
406+}
407+.card-pill {
408+ font-size: 10.5px;
409+ font-weight: 700;
410+ text-transform: uppercase;
411+ letter-spacing: 0.06em;
412+ padding: 3px 9px;
413+ border-radius: 999px;
414+ border: 1px solid var(--line-2);
415+ background: var(--surface-2);
416+ color: var(--muted);
417+}
418+.card h2 {
419+ margin: 0 0 8px;
420+ font-size: 21px;
421+ font-weight: 700;
422+ letter-spacing: -0.01em;
423+}
424+.card-desc {
425+ margin: 0 0 18px;
426+ color: var(--muted);
427+ font-size: 13.5px;
428+ line-height: 1.55;
429+ flex: 1;
430+}
431+.card-links {
432+ list-style: none;
433+ margin: 0 0 20px;
434+ padding: 0;
435+ display: flex;
436+ flex-direction: column;
437+ gap: 6px;
438+}
439+.card-links li {
440+ font-size: 13px;
441+ color: var(--muted);
442+ display: flex;
443+ align-items: center;
444+ gap: 8px;
445+}
446+.card-links li::before {
447+ content: "";
448+ width: 5px;
449+ height: 5px;
450+ border-radius: 999px;
451+ background: var(--faint);
452+ flex-shrink: 0;
453+}
454+.card-footer {
455+ display: flex;
456+ align-items: center;
457+ justify-content: space-between;
458+ padding-top: 14px;
459+ border-top: 1px solid var(--line);
460+ font-size: 13px;
461+}
462+.page-count { color: var(--faint); font-weight: 500; font-size: 12px; }
463+.card-cta {
464+ color: var(--accent-light);
465+ font-weight: 600;
466+ display: inline-flex;
467+ align-items: center;
468+ gap: 5px;
469+ transition: transform 0.15s;
470+}
471+.card:hover .card-cta { transform: translateX(3px); }
472+
473+/* Quick Start Grid */
474+.quickstart-section { margin-bottom: 40px; }
475+.quickstart-grid {
476+ display: grid;
477+ grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
478+ gap: 16px;
479+}
480+.quick-card {
481+ display: flex;
482+ align-items: center;
483+ gap: 14px;
484+ padding: 18px 20px;
485+ border-radius: 14px;
486+ border: 1px solid var(--line);
487+ background: var(--surface);
488+ text-decoration: none;
489+ color: var(--text);
490+ transition: all 0.15s ease;
491+}
492+.quick-card:hover {
493+ border-color: var(--line-2);
494+ background: var(--surface-2);
495+ transform: translateY(-2px);
496+}
497+.quick-icon {
498+ width: 38px;
499+ height: 38px;
500+ border-radius: 10px;
501+ background: var(--surface-2);
502+ border: 1px solid var(--line-2);
503+ color: var(--muted);
504+ display: flex;
505+ align-items: center;
506+ justify-content: center;
507+ flex-shrink: 0;
508+}
509+.quick-card:hover .quick-icon {
510+ color: var(--accent-light);
511+ border-color: rgba(224, 93, 118, 0.3);
512+}
513+.quick-content { flex: 1; min-width: 0; }
514+.quick-badge {
515+ display: inline-block;
516+ font-size: 10.5px;
517+ font-weight: 700;
518+ text-transform: uppercase;
519+ letter-spacing: 0.06em;
520+ color: var(--accent-light);
521+ margin-bottom: 2px;
522+}
523+.quick-card h3 {
524+ margin: 0;
525+ font-size: 14.5px;
526+ font-weight: 600;
527+ color: var(--strong);
528+}
529+.quick-card p {
530+ margin: 2px 0 0;
531+ font-size: 12.5px;
532+ color: var(--faint);
533+ overflow: hidden;
534+ text-overflow: ellipsis;
535+ white-space: nowrap;
536+}
537+.quick-arrow {
538+ color: var(--faint);
539+ flex-shrink: 0;
540+ transition: transform 0.15s, color 0.15s;
541+}
542+.quick-card:hover .quick-arrow {
543+ color: var(--strong);
544+ transform: translateX(3px);
545+}
91546
92547 /* Documentation page */
93−.doc { max-width: 1360px; margin: 0 auto; width: 100%; flex: 1; display: grid; grid-template-columns: 250px minmax(0, 1fr) 220px; gap: 40px; padding: 0 20px; }
94−.sidebar, .toc { position: sticky; top: 64px; align-self: start; max-height: calc(100vh - 64px); overflow-y: auto; padding: 28px 0; }
95−.sidebar-title, .toc-title { margin: 0 0 10px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--faint); }
548+.doc {
549+ max-width: 1360px;
550+ margin: 0 auto;
551+ width: 100%;
552+ flex: 1;
553+ display: grid;
554+ grid-template-columns: 260px minmax(0, 1fr) 230px;
555+ gap: 48px;
556+ padding: 0 24px;
557+}
558+.sidebar, .toc {
559+ position: sticky;
560+ top: 64px;
561+ align-self: start;
562+ max-height: calc(100vh - 64px);
563+ overflow-y: auto;
564+ padding: 32px 0;
565+}
566+.sidebar::-webkit-scrollbar, .toc::-webkit-scrollbar { width: 5px; }
567+.sidebar::-webkit-scrollbar-thumb, .toc::-webkit-scrollbar-thumb {
568+ background: rgba(255, 255, 255, 0.1);
569+ border-radius: 10px;
570+}
571+.sidebar-title, .toc-title {
572+ margin: 0 0 12px;
573+ font-size: 11.5px;
574+ font-weight: 700;
575+ text-transform: uppercase;
576+ letter-spacing: 0.08em;
577+ color: var(--faint);
578+}
96579 .sidebar ul, .toc ul, .sidebar-mobile ul { list-style: none; margin: 0; padding: 0; }
97−.sidebar a, .sidebar-mobile a { display: block; padding: 6px 10px; border-radius: 8px; font-size: 14px; color: var(--muted); text-decoration: none; }
98−.sidebar a:hover, .sidebar-mobile a:hover { color: var(--strong); background: var(--surface); }
99−.sidebar a[aria-current="page"], .sidebar-mobile a[aria-current="page"] { color: var(--strong); background: var(--surface); font-weight: 600; box-shadow: inset 2px 0 0 var(--accent-light); }
100−.toc a { display: block; padding: 4px 0; font-size: 13px; color: var(--muted); text-decoration: none; }
580+.sidebar a, .sidebar-mobile a {
581+ display: block;
582+ padding: 7px 12px;
583+ border-radius: 9px;
584+ font-size: 13.5px;
585+ color: var(--muted);
586+ text-decoration: none;
587+ transition: all 0.15s ease;
588+}
589+.sidebar a:hover, .sidebar-mobile a:hover {
590+ color: var(--strong);
591+ background: var(--surface);
592+}
593+.sidebar a[aria-current="page"], .sidebar-mobile a[aria-current="page"] {
594+ color: var(--strong);
595+ background: var(--surface);
596+ font-weight: 600;
597+ border-left: 2px solid var(--accent-light);
598+ border-radius: 0 9px 9px 0;
599+}
600+.toc a {
601+ display: block;
602+ padding: 5px 0;
603+ font-size: 13px;
604+ color: var(--muted);
605+ text-decoration: none;
606+ transition: color 0.15s;
607+}
101608 .toc a:hover { color: var(--strong); }
102−.toc li.sub a { padding-left: 12px; font-size: 12.5px; }
609+.toc li.sub a { padding-left: 14px; font-size: 12.5px; color: var(--faint); }
610+.toc li.sub a:hover { color: var(--muted); }
103611 .sidebar-mobile { display: none; }
104612 .article { min-width: 0; max-width: 780px; padding: 32px 0 64px; }
105−.breadcrumb { margin: 0 0 8px; font-size: 13px; color: var(--faint); }
613+.breadcrumb {
614+ margin: 0 0 10px;
615+ font-size: 12.5px;
616+ color: var(--faint);
617+ display: flex;
618+ align-items: center;
619+ gap: 6px;
620+}
106621 .breadcrumb a { color: var(--muted); text-decoration: none; }
107622 .breadcrumb a:hover { color: var(--accent-light); }
108−.article > h1 { font-size: clamp(28px, 4vw, 36px); margin: 0 0 10px; letter-spacing: -0.015em; }
109−.lead { margin: 0 0 28px; font-size: 18px; color: var(--muted); }
623+.article > h1 {
624+ font-size: clamp(28px, 4vw, 38px);
625+ margin: 0 0 12px;
626+ font-weight: 800;
627+ letter-spacing: -0.02em;
628+}
629+.lead { margin: 0 0 32px; font-size: 17px; color: var(--muted); line-height: 1.6; }
110630
111−/* Content */
112−.prose h2 { font-size: 23px; margin: 44px 0 12px; padding-top: 16px; border-top: 1px solid var(--line); }
113−.prose h3 { font-size: 18px; margin: 30px 0 8px; }
114−.prose h4 { font-size: 16px; margin: 22px 0 6px; }
631+/* Prose / Markdown Content */
632+.prose h2 {
633+ font-size: 24px;
634+ font-weight: 700;
635+ margin: 48px 0 14px;
636+ padding-top: 18px;
637+ border-top: 1px solid var(--line);
638+}
639+.prose h3 { font-size: 19px; font-weight: 600; margin: 32px 0 10px; }
640+.prose h4 { font-size: 16px; font-weight: 600; margin: 24px 0 8px; }
115641 .prose h2, .prose h3, .prose h4 { position: relative; }
116−.prose .anchor { position: absolute; left: -22px; color: var(--faint); text-decoration: none; opacity: 0; font-weight: 500; }
642+.prose .anchor {
643+ position: absolute;
644+ left: -24px;
645+ color: var(--faint);
646+ text-decoration: none;
647+ opacity: 0;
648+ font-weight: 500;
649+ transition: opacity 0.15s;
650+}
117651 .prose h2:hover .anchor, .prose h3:hover .anchor, .prose h4:hover .anchor { opacity: 1; }
118−.prose p, .prose ul, .prose ol { margin: 0 0 16px; }
119−.prose li { margin: 4px 0; }
120−.prose li > ul, .prose li > ol { margin: 4px 0; }
121−.prose strong { color: var(--strong); }
122−.prose a { text-underline-offset: 3px; }
123−.prose :not(pre) > code { font-size: 0.88em; padding: 2px 6px; border-radius: 6px; background: var(--inline-code); color: var(--strong); white-space: break-spaces; }
124−.prose hr { border: 0; border-top: 1px solid var(--line); margin: 32px 0; }
125−.prose blockquote { margin: 0 0 16px; padding: 2px 16px; border-left: 3px solid var(--line-2); color: var(--muted); }
652+.prose p, .prose ul, .prose ol { margin: 0 0 18px; }
653+.prose li { margin: 5px 0; }
654+.prose li > ul, .prose li > ol { margin: 5px 0; }
655+.prose strong { color: var(--strong); font-weight: 600; }
656+.prose a { text-underline-offset: 3px; font-weight: 500; }
657+.prose a:hover { text-decoration: underline; }
658+.prose :not(pre) > code {
659+ font-size: 0.88em;
660+ padding: 3px 7px;
661+ border-radius: 6px;
662+ background: var(--inline-code);
663+ border: 1px solid var(--line);
664+ color: var(--strong);
665+ white-space: break-spaces;
666+}
667+.prose hr { border: 0; border-top: 1px solid var(--line); margin: 36px 0; }
668+.prose blockquote {
669+ margin: 0 0 18px;
670+ padding: 4px 18px;
671+ border-left: 3px solid var(--line-2);
672+ color: var(--muted);
673+ font-style: italic;
674+}
126675 .prose img { max-width: 100%; border-radius: 12px; border: 1px solid var(--line); }
127676
128−.code { position: relative; margin: 0 0 18px; border-radius: 12px; border: 1px solid var(--line); background: var(--code-bg); overflow: hidden; }
129−.code pre { margin: 0; padding: 16px 18px; overflow-x: auto; font-size: 13.5px; line-height: 1.6; background: transparent !important; }
130−.code-lang { position: absolute; top: 8px; left: 14px; font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--faint); font-family: var(--font-mono), monospace; pointer-events: none; }
131−.code:has(.code-lang) pre { padding-top: 30px; }
132−.code-copy { position: absolute; top: 7px; right: 8px; font: inherit; font-size: 12px; padding: 3px 9px; border-radius: 7px; border: 1px solid var(--line-2); background: var(--surface); color: var(--muted); cursor: pointer; opacity: 0; transition: opacity 0.15s; }
677+/* Code Blocks */
678+.code {
679+ position: relative;
680+ margin: 0 0 22px;
681+ border-radius: 14px;
682+ border: 1px solid var(--line);
683+ background: var(--code-bg);
684+ overflow: hidden;
685+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
686+}
687+.code pre {
688+ margin: 0;
689+ padding: 18px 20px;
690+ overflow-x: auto;
691+ font-size: 13.5px;
692+ line-height: 1.6;
693+ background: transparent !important;
694+}
695+.code-lang {
696+ position: absolute;
697+ top: 9px;
698+ left: 16px;
699+ font-size: 10px;
700+ text-transform: uppercase;
701+ letter-spacing: 0.08em;
702+ color: var(--faint);
703+ font-family: var(--font-mono), monospace;
704+ pointer-events: none;
705+}
706+.code:has(.code-lang) pre { padding-top: 32px; }
707+.code-copy {
708+ position: absolute;
709+ top: 8px;
710+ right: 10px;
711+ font: inherit;
712+ font-size: 11.5px;
713+ padding: 4px 10px;
714+ border-radius: 7px;
715+ border: 1px solid var(--line-2);
716+ background: var(--surface);
717+ color: var(--muted);
718+ cursor: pointer;
719+ opacity: 0;
720+ transition: opacity 0.15s, background 0.15s;
721+}
133722 .code:hover .code-copy, .code-copy:focus-visible { opacity: 1; }
723+.code-copy:hover { background: var(--surface-2); color: var(--strong); }
134724 .shiki span { color: var(--shiki-dark); }
135725 :root[data-theme="light"] .shiki span { color: var(--shiki-light); }
136726 @media (prefers-color-scheme: light) { :root:not([data-theme]) .shiki span { color: var(--shiki-light); } }
137727
138−.table { margin: 0 0 18px; overflow-x: auto; border: 1px solid var(--line); border-radius: 12px; }
728+/* Tables */
729+.table { margin: 0 0 22px; overflow-x: auto; border: 1px solid var(--line); border-radius: 14px; }
139730 .table table { width: 100%; border-collapse: collapse; font-size: 14px; }
140−.table th, .table td { padding: 9px 14px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
731+.table th, .table td { padding: 10px 16px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
141732 .table th { font-weight: 600; color: var(--strong); background: var(--surface-2); }
142733 .table tr:last-child td { border-bottom: 0; }
143734
144−.callout { margin: 0 0 18px; padding: 12px 16px; border-radius: 12px; border: 1px solid var(--line); border-left: 3px solid var(--note); background: var(--note-soft); }
735+/* Callouts */
736+.callout {
737+ margin: 0 0 22px;
738+ padding: 14px 18px;
739+ border-radius: 14px;
740+ border: 1px solid var(--line);
741+ border-left: 4px solid var(--note);
742+ background: var(--note-soft);
743+}
145744 .callout > :last-child { margin-bottom: 0; }
146−.callout-title { margin: 0 0 4px !important; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--note); }
147−.callout.tip { border-left-color: var(--tip); background: var(--tip-soft); } .callout.tip .callout-title { color: var(--tip); }
148−.callout.warning { border-left-color: var(--warn); background: var(--warn-soft); } .callout.warning .callout-title { color: var(--warn); }
149−.callout.danger { border-left-color: var(--danger); background: var(--danger-soft); } .callout.danger .callout-title { color: var(--danger); }
745+.callout-title {
746+ margin: 0 0 6px !important;
747+ font-size: 12.5px;
748+ font-weight: 700;
749+ text-transform: uppercase;
750+ letter-spacing: 0.07em;
751+ color: var(--note);
752+}
753+.callout.tip { border-left-color: var(--tip); background: var(--tip-soft); }
754+.callout.tip .callout-title { color: var(--tip); }
755+.callout.warning { border-left-color: var(--warn); background: var(--warn-soft); }
756+.callout.warning .callout-title { color: var(--warn); }
757+.callout.danger { border-left-color: var(--danger); background: var(--danger-soft); }
758+.callout.danger .callout-title { color: var(--danger); }
150759
151−.pager { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 48px; padding-top: 24px; border-top: 1px solid var(--line); }
152−.pager-link { display: flex; flex-direction: column; gap: 2px; padding: 14px 16px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); color: var(--strong); text-decoration: none; font-weight: 600; font-size: 15px; }
153−.pager-link span { font-size: 12px; font-weight: 500; color: var(--faint); }
154−.pager-link:hover { border-color: color-mix(in srgb, var(--accent-light) 45%, transparent); }
760+/* Pager */
761+.pager {
762+ display: grid;
763+ grid-template-columns: 1fr 1fr;
764+ gap: 16px;
765+ margin-top: 56px;
766+ padding-top: 28px;
767+ border-top: 1px solid var(--line);
768+}
769+.pager-link {
770+ display: flex;
771+ flex-direction: column;
772+ gap: 3px;
773+ padding: 16px 20px;
774+ border-radius: 14px;
775+ border: 1px solid var(--line);
776+ background: var(--surface);
777+ color: var(--strong);
778+ text-decoration: none;
779+ font-weight: 600;
780+ font-size: 15px;
781+ transition: all 0.15s ease;
782+}
783+.pager-link span { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--faint); }
784+.pager-link:hover {
785+ border-color: rgba(224, 93, 118, 0.4);
786+ transform: translateY(-2px);
787+ background: var(--surface-2);
788+}
155789 .pager-link.next { text-align: right; grid-column: 2; }
156790
157−/* Error page and footer */
158−.error-page { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 64px 20px; }
159−.error-page img { object-fit: contain; margin-bottom: 18px; }
160−.error-code { margin: 0; font-family: var(--font-mono), monospace; font-weight: 600; letter-spacing: 0.2em; color: var(--accent-light); }
161−.error-page h1 { font-size: 34px; margin: 6px 0 10px; }
162−.error-page > p:not(.error-code) { max-width: 480px; color: var(--muted); margin: 0 0 24px; }
163−.footer { border-top: 1px solid var(--line); color: var(--faint); font-size: 13px; }
164−.footer-in { max-width: 1360px; margin: 0 auto; padding: 20px; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; }
165−.footer-links { display: flex; gap: 16px; }
166−.footer-links a { color: var(--muted); text-decoration: none; }
167−.footer-links a:hover { color: var(--accent-light); }
791+/* Footer */
792+.footer { border-top: 1px solid var(--line); color: var(--faint); font-size: 13px; margin-top: auto; }
793+.footer-in {
794+ max-width: 1360px;
795+ margin: 0 auto;
796+ padding: 24px;
797+ display: flex;
798+ justify-content: space-between;
799+ align-items: center;
800+ flex-wrap: wrap;
801+ gap: 12px;
802+}
803+.footer-links { display: flex; gap: 20px; }
804+.footer-links a { color: var(--muted); text-decoration: none; transition: color 0.15s; }
805+.footer-links a:hover { color: var(--strong); }
168806
807+/* Responsive */
169808 @media (max-width: 1180px) {
170− .doc { grid-template-columns: 230px minmax(0, 1fr); }
809+ .doc { grid-template-columns: 240px minmax(0, 1fr); gap: 32px; }
171810 .toc { display: none; }
172811 }
173812 @media (max-width: 900px) {
174813 .header-in .tabs { display: none; }
175− .tabs-mobile { display: flex; overflow-x: auto; padding: 0 12px 10px; max-width: 1360px; margin: 0 auto; }
814+ .tabs-mobile {
815+ display: flex;
816+ overflow-x: auto;
817+ padding: 0 16px 12px;
818+ max-width: 1360px;
819+ margin: 0 auto;
820+ gap: 4px;
821+ }
176822 .search-button { min-width: 0; }
177823 .search-label, .search-button kbd, .header-right .site { display: none; }
178− .doc { grid-template-columns: minmax(0, 1fr); }
824+ .doc { grid-template-columns: minmax(0, 1fr); padding: 0 16px; }
179825 .sidebar { display: none; }
180− .sidebar-mobile { display: block; margin: 0 0 18px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--line); background: var(--surface); }
826+ .sidebar-mobile {
827+ display: block;
828+ margin: 0 0 20px;
829+ padding: 12px 16px;
830+ border-radius: 12px;
831+ border: 1px solid var(--line);
832+ background: var(--surface);
833+ }
181834 .sidebar-mobile summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--strong); }
182− .sidebar-mobile ul { margin-top: 8px; }
183− .article { padding-top: 22px; }
835+ .sidebar-mobile ul { margin-top: 10px; }
836+ .article { padding-top: 20px; }
184837 .prose .anchor { display: none; }
185838 .header .tabs-mobile a[aria-current="page"] { box-shadow: none; }
186839 }
@@ -188,4 +841,7 @@ kbd { font-size: 11px; padding: 1px 6px; border-radius: 6px; border: 1px solid v
188841 .tag { display: none; }
189842 .pager { grid-template-columns: 1fr; }
190843 .pager-link.next { grid-column: 1; }
844+ .home { padding: 40px 16px 64px; }
845+ .cards { grid-template-columns: 1fr; }
846+ .quickstart-grid { grid-template-columns: 1fr; }
191847 }
Modifiésrc/app/page.tsx+131−20
@@ -1,32 +1,143 @@
11 import Link from "next/link";
22 import { listPages } from "@/lib/content";
33 import { SECTIONS } from "@/lib/sections";
4+import {
5+ IconServer,
6+ IconTerminal,
7+ IconGitBranch,
8+ IconActivity,
9+ IconArrowRight,
10+ IconBookOpen,
11+ IconCode,
12+} from "@/components/Icons";
13+
14+const SECTION_ICONS: Record<string, typeof IconServer> = {
15+ hebergement: IconServer,
16+ api: IconTerminal,
17+ git: IconGitBranch,
18+ status: IconActivity,
19+};
20+
21+const SECTION_BADGES: Record<string, string> = {
22+ hebergement: "Cloud & Bare-Metal",
23+ api: "REST API & CLI",
24+ git: "Forge Souveraine",
25+ status: "Haute Disponibilité",
26+};
27+
28+const QUICK_STARTS = [
29+ {
30+ title: "Déploiement Git continu",
31+ desc: "Connecter vos dépôts pour déployer automatiquement à chaque push.",
32+ href: "/hebergement/deploiement-git/",
33+ section: "Hébergement",
34+ icon: IconGitBranch,
35+ },
36+ {
37+ title: "Authentification API",
38+ desc: "Générer un jeton dim_live_ et configurer les permissions requises.",
39+ href: "/api/",
40+ section: "API & CLI",
41+ icon: IconCode,
42+ },
43+ {
44+ title: "Accès SSH & Terminal VPS",
45+ desc: "Se connecter directement en SSH sur le port 22 ou via le shell web.",
46+ href: "/hebergement/vps/",
47+ section: "Hébergement",
48+ icon: IconTerminal,
49+ },
50+ {
51+ title: "Heartbeat & API Statut",
52+ desc: "Interroger les métriques de disponibilité et l'état des sondes en JSON.",
53+ href: "/status/api/",
54+ section: "Dimdam's Status",
55+ icon: IconActivity,
56+ },
57+];
458
5−/** Home: one card per documentation, with its first pages. */
659 export default function Home() {
760 return (
861 <main className="home">
62+ {/* Hero Header */}
963 <section className="hero">
10− <h1>Documentation Dimdam&apos;s</h1>
11− <p>Tout pour héberger, automatiser et suivre vos projets sur Dimdam&apos;s. Choisissez une documentation, ou cherchez directement (Ctrl K).</p>
64+ <div className="hero-badge">
65+ <span className="live-dot" />
66+ <span>Documentation technique officielle</span>
67+ </div>
68+ <h1>Tout l&apos;écosystème Dimdam&apos;s documenté.</h1>
69+ <p>
70+ Guides de configuration, tutoriels pas-à-pas pour vos conteneurs et VPS,
71+ spécification exhaustive de l&apos;API REST et intégration de la forge logicielle.
72+ </p>
73+ </section>
74+
75+ {/* Main 4 Products Grid */}
76+ <section className="cards-section">
77+ <div className="section-label">
78+ <IconBookOpen width={16} height={16} />
79+ <span>Produits & Services</span>
80+ </div>
81+ <div className="cards">
82+ {SECTIONS.map((s) => {
83+ const pages = listPages(s.id).filter((p) => p.slug !== "index");
84+ const Icon = SECTION_ICONS[s.id] ?? IconBookOpen;
85+ const badge = SECTION_BADGES[s.id] ?? "Documentation";
86+
87+ return (
88+ <Link key={s.id} href={`/${s.id}/`} className="card">
89+ <div className="card-header">
90+ <div className="card-icon">
91+ <Icon width={22} height={22} />
92+ </div>
93+ <span className="card-pill">{badge}</span>
94+ </div>
95+ <h2>{s.title}</h2>
96+ <p className="card-desc">{s.description}</p>
97+ <ul className="card-links">
98+ {pages.slice(0, 4).map((p) => (
99+ <li key={p.slug}>
100+ <span>{p.title}</span>
101+ </li>
102+ ))}
103+ </ul>
104+ <div className="card-footer">
105+ <span className="page-count">{pages.length} articles</span>
106+ <span className="card-cta">
107+ Explorer <IconArrowRight width={14} height={14} />
108+ </span>
109+ </div>
110+ </Link>
111+ );
112+ })}
113+ </div>
114+ </section>
115+
116+ {/* Quick Start / Most Visited Guides */}
117+ <section className="quickstart-section">
118+ <div className="section-label">
119+ <IconTerminal width={16} height={16} />
120+ <span>Démarrage rapide & Guides essentiels</span>
121+ </div>
122+ <div className="quickstart-grid">
123+ {QUICK_STARTS.map((q) => {
124+ const Icon = q.icon;
125+ return (
126+ <Link key={q.href} href={q.href} className="quick-card">
127+ <div className="quick-icon">
128+ <Icon width={18} height={18} />
129+ </div>
130+ <div className="quick-content">
131+ <span className="quick-badge">{q.section}</span>
132+ <h3>{q.title}</h3>
133+ <p>{q.desc}</p>
134+ </div>
135+ <IconArrowRight width={16} height={16} className="quick-arrow" />
136+ </Link>
137+ );
138+ })}
139+ </div>
12140 </section>
13− <div className="cards">
14− {SECTIONS.map((s) => {
15− const pages = listPages(s.id).filter((p) => p.slug !== "index");
16− return (
17− <Link key={s.id} href={`/${s.id}/`} className="card">
18− <h2>{s.title}</h2>
19− <p>{s.description}</p>
20− <ul>
21− {pages.slice(0, 4).map((p) => (
22− <li key={p.slug}>{p.title}</li>
23− ))}
24− </ul>
25− <span className="card-more">{pages.length} pages →</span>
26− </Link>
27− );
28− })}
29− </div>
30141 </main>
31142 );
32143 }
Ajoutésrc/components/Icons.tsx+85−0
@@ -0,0 +1,85 @@
1+import type { SVGProps } from "react";
2+
3+export function IconServer(props: SVGProps<SVGSVGElement>) {
4+ return (
5+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
6+ <rect width="20" height="8" x="2" y="2" rx="2" ry="2" />
7+ <rect width="20" height="8" x="2" y="14" rx="2" ry="2" />
8+ <line x1="6" x2="6.01" y1="6" y2="6" />
9+ <line x1="6" x2="6.01" y1="18" y2="18" />
10+ </svg>
11+ );
12+}
13+
14+export function IconTerminal(props: SVGProps<SVGSVGElement>) {
15+ return (
16+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
17+ <polyline points="4 17 10 11 4 5" />
18+ <line x1="12" x2="20" y1="19" y2="19" />
19+ </svg>
20+ );
21+}
22+
23+export function IconGitBranch(props: SVGProps<SVGSVGElement>) {
24+ return (
25+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
26+ <line x1="6" x2="6" y1="3" y2="15" />
27+ <circle cx="18" cy="6" r="3" />
28+ <circle cx="6" cy="18" r="3" />
29+ <path d="M18 9a9 9 0 0 1-9 9" />
30+ </svg>
31+ );
32+}
33+
34+export function IconActivity(props: SVGProps<SVGSVGElement>) {
35+ return (
36+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
37+ <path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.48 12H2" />
38+ </svg>
39+ );
40+}
41+
42+export function IconBookOpen(props: SVGProps<SVGSVGElement>) {
43+ return (
44+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
45+ <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />
46+ <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
47+ </svg>
48+ );
49+}
50+
51+export function IconArrowRight(props: SVGProps<SVGSVGElement>) {
52+ return (
53+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
54+ <path d="M5 12h14" />
55+ <path d="m12 5 7 7-7 7" />
56+ </svg>
57+ );
58+}
59+
60+export function IconShield(props: SVGProps<SVGSVGElement>) {
61+ return (
62+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
63+ <path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" />
64+ </svg>
65+ );
66+}
67+
68+export function IconExternalLink(props: SVGProps<SVGSVGElement>) {
69+ return (
70+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
71+ <path d="M15 3h6v6" />
72+ <path d="M10 14 21 3" />
73+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
74+ </svg>
75+ );
76+}
77+
78+export function IconCode(props: SVGProps<SVGSVGElement>) {
79+ return (
80+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}>
81+ <polyline points="16 18 22 12 16 6" />
82+ <polyline points="8 6 2 12 8 18" />
83+ </svg>
84+ );
85+}