index.html 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607
  1. <!DOCTYPE html>
  2. <html lang="fr">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta name="description" content="Bastien Chanot — Développeur Systèmes · Embarqué · Backend. 7 ans en C, Rust, Linux kernel, AOSP, cloud gaming et GPU bare-metal en production.">
  7. <meta name="author" content="Bastien Chanot">
  8. <meta name="theme-color" content="#0d1b12">
  9. <title>Bastien Chanot — Développeur Systèmes · Embarqué · Backend</title>
  10. <link rel="preconnect" href="https://fonts.googleapis.com">
  11. <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  12. <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Fraunces:ital,wght@0,300;0,500;0,600;0,700;1,400&family=DM+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
  13. <style>
  14. :root {
  15. /* Palette — non négociable */
  16. --dark: #0d1b12;
  17. --dark-mid: #183325;
  18. --g900: #0e3320;
  19. --g700: #1b5e3b;
  20. --g500: #2d7a4f;
  21. --g300: #6ab98a;
  22. --g100: #dff0e7;
  23. --g050: #eef7f1;
  24. --ink-1: #111111;
  25. --ink-2: #1e1e1e;
  26. --ink-3: #636363;
  27. --page: #f5f3ec;
  28. --rule: #d8d4c8;
  29. --tag: #e6e2d8;
  30. /* Typographies */
  31. --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, monospace;
  32. --serif: 'Fraunces', Georgia, serif;
  33. --sans: 'DM Sans', system-ui, -apple-system, sans-serif;
  34. /* Échelle */
  35. --r-sm: 4px;
  36. --r-md: 6px;
  37. --r-pill: 999px;
  38. --shadow-sm: 0 1px 2px rgba(13, 27, 18, 0.06);
  39. --shadow-md: 0 6px 24px rgba(13, 27, 18, 0.08);
  40. --shadow-lg: 0 20px 60px rgba(13, 27, 18, 0.12);
  41. --nav-h: 64px;
  42. --max-w: 1100px;
  43. }
  44. *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
  45. html { scroll-behavior: smooth; scroll-padding-top: calc(var(--nav-h) + 16px); }
  46. body {
  47. background: var(--page);
  48. color: var(--ink-2);
  49. font-family: var(--sans);
  50. font-size: 16px;
  51. line-height: 1.6;
  52. -webkit-font-smoothing: antialiased;
  53. -moz-osx-font-smoothing: grayscale;
  54. overflow-x: hidden;
  55. }
  56. ::selection { background: var(--g300); color: var(--dark); }
  57. a { color: var(--g700); text-decoration: none; transition: color .18s ease; }
  58. a:hover { color: var(--g500); }
  59. a:focus-visible { outline: 2px solid var(--g500); outline-offset: 3px; border-radius: 2px; }
  60. button, .btn { font-family: inherit; cursor: pointer; }
  61. /* ── NAV ── */
  62. .nav {
  63. position: fixed;
  64. top: 0; left: 0; right: 0;
  65. height: var(--nav-h);
  66. background: rgba(13, 27, 18, 0.92);
  67. backdrop-filter: saturate(140%) blur(10px);
  68. -webkit-backdrop-filter: saturate(140%) blur(10px);
  69. border-bottom: 1px solid rgba(106, 185, 138, 0.12);
  70. z-index: 50;
  71. }
  72. .nav-inner {
  73. max-width: var(--max-w);
  74. height: 100%;
  75. margin: 0 auto;
  76. padding: 0 24px;
  77. display: flex;
  78. align-items: center;
  79. justify-content: space-between;
  80. gap: 24px;
  81. }
  82. .brand {
  83. font-family: var(--mono);
  84. font-size: 14px;
  85. font-weight: 600;
  86. color: var(--g100);
  87. letter-spacing: 0.5px;
  88. display: inline-flex;
  89. align-items: center;
  90. gap: 8px;
  91. }
  92. .brand::before {
  93. content: "";
  94. width: 8px; height: 8px;
  95. border-radius: 50%;
  96. background: var(--g300);
  97. box-shadow: 0 0 0 0 rgba(106,185,138,.7);
  98. animation: pulse 2.4s infinite;
  99. }
  100. @keyframes pulse {
  101. 0% { box-shadow: 0 0 0 0 rgba(106,185,138,.5); }
  102. 70% { box-shadow: 0 0 0 10px rgba(106,185,138,0); }
  103. 100% { box-shadow: 0 0 0 0 rgba(106,185,138,0); }
  104. }
  105. .nav-links { display: flex; gap: 4px; list-style: none; }
  106. .nav-links a {
  107. font-family: var(--mono);
  108. font-size: 13px;
  109. color: rgba(223, 240, 231, 0.75);
  110. padding: 8px 12px;
  111. border-radius: var(--r-sm);
  112. transition: color .18s ease, background .18s ease;
  113. }
  114. .nav-links a:hover { color: var(--g100); background: rgba(106,185,138,0.08); }
  115. .nav-toggle { display: none; }
  116. @media (max-width: 768px) {
  117. .nav-links {
  118. position: absolute;
  119. top: var(--nav-h); left: 0; right: 0;
  120. flex-direction: column;
  121. gap: 0;
  122. background: var(--dark);
  123. border-bottom: 1px solid rgba(106,185,138,0.12);
  124. padding: 8px 0;
  125. transform: translateY(-200%);
  126. transition: transform .25s ease;
  127. }
  128. .nav-links.open { transform: translateY(0); }
  129. .nav-links a { padding: 14px 24px; border-radius: 0; }
  130. .nav-toggle {
  131. display: inline-flex;
  132. align-items: center;
  133. justify-content: center;
  134. width: 40px; height: 40px;
  135. margin-left: auto;
  136. background: transparent;
  137. border: 1px solid rgba(106,185,138,0.25);
  138. border-radius: var(--r-sm);
  139. color: var(--g100);
  140. }
  141. .nav-toggle svg { width: 18px; height: 18px; }
  142. }
  143. /* ── LAYOUT ── */
  144. main { padding-top: var(--nav-h); }
  145. section { padding: 96px 24px; }
  146. .container { max-width: var(--max-w); margin: 0 auto; }
  147. .section-label {
  148. display: inline-flex;
  149. align-items: center;
  150. gap: 10px;
  151. font-family: var(--mono);
  152. font-size: 12px;
  153. font-weight: 600;
  154. color: var(--g500);
  155. letter-spacing: 0.12em;
  156. text-transform: uppercase;
  157. margin-bottom: 18px;
  158. }
  159. .section-label::before {
  160. content: "";
  161. width: 24px; height: 1px; background: var(--g500);
  162. }
  163. .section-dark .section-label { color: var(--g300); }
  164. .section-dark .section-label::before { background: var(--g300); }
  165. h2.section-title {
  166. font-family: var(--serif);
  167. font-weight: 600;
  168. font-size: clamp(28px, 4vw, 40px);
  169. line-height: 1.1;
  170. color: var(--ink-1);
  171. letter-spacing: -0.02em;
  172. margin-bottom: 20px;
  173. }
  174. .section-dark h2.section-title { color: #fff; }
  175. .section-intro {
  176. font-family: var(--sans);
  177. font-size: 17px;
  178. color: var(--ink-2);
  179. max-width: 64ch;
  180. }
  181. .section-dark .section-intro { color: rgba(223, 240, 231, 0.85); }
  182. /* ── HERO ── */
  183. .hero {
  184. position: relative;
  185. min-height: calc(100vh - var(--nav-h));
  186. padding: 80px 24px 96px;
  187. display: flex;
  188. align-items: center;
  189. overflow: hidden;
  190. background:
  191. radial-gradient(ellipse 80% 60% at 80% 0%, rgba(45,122,79,0.10) 0%, transparent 60%),
  192. radial-gradient(ellipse 60% 50% at 0% 100%, rgba(27,94,59,0.08) 0%, transparent 55%),
  193. var(--page);
  194. }
  195. .hero-inner {
  196. max-width: var(--max-w);
  197. width: 100%;
  198. margin: 0 auto;
  199. display: grid;
  200. grid-template-columns: 1fr;
  201. gap: 28px;
  202. position: relative;
  203. }
  204. .hero-eyebrow {
  205. font-family: var(--mono);
  206. font-size: 13px;
  207. color: var(--g700);
  208. letter-spacing: 0.08em;
  209. display: inline-flex;
  210. align-items: center;
  211. gap: 10px;
  212. }
  213. .hero-eyebrow::before {
  214. content: "▍";
  215. color: var(--g500);
  216. font-weight: 700;
  217. }
  218. .hero-name {
  219. font-family: var(--serif);
  220. font-size: clamp(48px, 8vw, 96px);
  221. font-weight: 600;
  222. line-height: 0.95;
  223. letter-spacing: -0.04em;
  224. color: var(--ink-1);
  225. }
  226. .hero-name em {
  227. font-style: italic;
  228. font-weight: 400;
  229. color: var(--g700);
  230. }
  231. .hero-title {
  232. font-family: var(--mono);
  233. font-size: clamp(14px, 1.6vw, 17px);
  234. color: var(--ink-2);
  235. font-weight: 500;
  236. letter-spacing: 0.02em;
  237. }
  238. .hero-title .sep { color: var(--g500); margin: 0 8px; }
  239. .hero-tagline {
  240. font-family: var(--serif);
  241. font-style: italic;
  242. font-weight: 300;
  243. font-size: clamp(20px, 2.6vw, 28px);
  244. line-height: 1.35;
  245. color: var(--ink-2);
  246. max-width: 56ch;
  247. border-left: 3px solid var(--g500);
  248. padding-left: 20px;
  249. }
  250. .hero-cta {
  251. display: flex;
  252. gap: 14px;
  253. flex-wrap: wrap;
  254. margin-top: 12px;
  255. }
  256. .btn {
  257. display: inline-flex;
  258. align-items: center;
  259. gap: 10px;
  260. font-family: var(--mono);
  261. font-size: 14px;
  262. font-weight: 600;
  263. letter-spacing: 0.02em;
  264. padding: 14px 22px;
  265. border-radius: var(--r-md);
  266. border: 1px solid transparent;
  267. transition: transform .18s ease, background .18s ease, color .18s ease, border-color .18s ease, box-shadow .18s ease;
  268. text-decoration: none;
  269. }
  270. .btn-primary {
  271. background: var(--dark);
  272. color: var(--g100);
  273. border-color: var(--dark);
  274. box-shadow: var(--shadow-sm);
  275. }
  276. .btn-primary:hover {
  277. background: var(--g700);
  278. border-color: var(--g700);
  279. color: #fff;
  280. transform: translateY(-1px);
  281. box-shadow: var(--shadow-md);
  282. }
  283. .btn-secondary {
  284. background: transparent;
  285. color: var(--dark);
  286. border-color: var(--rule);
  287. }
  288. .btn-secondary:hover {
  289. border-color: var(--g500);
  290. color: var(--g700);
  291. background: var(--g050);
  292. transform: translateY(-1px);
  293. }
  294. .btn .arrow {
  295. width: 14px; height: 14px;
  296. transition: transform .18s ease;
  297. }
  298. .btn:hover .arrow { transform: translate(2px, -2px); }
  299. .hero-meta {
  300. display: flex;
  301. flex-wrap: wrap;
  302. gap: 24px;
  303. margin-top: 16px;
  304. font-family: var(--mono);
  305. font-size: 12px;
  306. color: var(--ink-3);
  307. letter-spacing: 0.04em;
  308. }
  309. .hero-meta span { display: inline-flex; align-items: center; gap: 8px; }
  310. .hero-meta .dot {
  311. display: inline-block;
  312. width: 6px; height: 6px;
  313. border-radius: 50%;
  314. background: var(--g500);
  315. }
  316. /* Stagger entrance */
  317. .reveal { opacity: 0; transform: translateY(14px); animation: rise .8s cubic-bezier(.2,.7,.2,1) forwards; }
  318. .reveal.d1 { animation-delay: .08s; }
  319. .reveal.d2 { animation-delay: .18s; }
  320. .reveal.d3 { animation-delay: .30s; }
  321. .reveal.d4 { animation-delay: .42s; }
  322. .reveal.d5 { animation-delay: .55s; }
  323. .reveal.d6 { animation-delay: .68s; }
  324. @keyframes rise {
  325. to { opacity: 1; transform: translateY(0); }
  326. }
  327. @media (prefers-reduced-motion: reduce) {
  328. .reveal { opacity: 1; transform: none; animation: none; }
  329. .brand::before { animation: none; }
  330. html { scroll-behavior: auto; }
  331. }
  332. /* ── ABOUT ── */
  333. .about {
  334. background: var(--dark);
  335. background-image:
  336. radial-gradient(ellipse 60% 50% at 100% 0%, rgba(45,122,79,0.16) 0%, transparent 55%),
  337. radial-gradient(ellipse 50% 40% at 0% 100%, rgba(27,94,59,0.12) 0%, transparent 60%);
  338. color: #fff;
  339. position: relative;
  340. }
  341. .about::before {
  342. content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  343. width: 3px;
  344. background: linear-gradient(to bottom, var(--g300), var(--g700));
  345. }
  346. .about-grid {
  347. display: grid;
  348. grid-template-columns: 1fr;
  349. gap: 32px;
  350. align-items: start;
  351. }
  352. .about-text p {
  353. font-size: 18px;
  354. line-height: 1.65;
  355. color: rgba(223, 240, 231, 0.92);
  356. margin-bottom: 16px;
  357. max-width: 62ch;
  358. }
  359. .about-text strong { color: var(--g300); font-weight: 500; }
  360. .about-callout {
  361. border: 1px solid rgba(106,185,138,0.25);
  362. border-radius: var(--r-md);
  363. padding: 20px 22px;
  364. background: rgba(13, 27, 18, 0.4);
  365. }
  366. .about-callout dt {
  367. font-family: var(--mono);
  368. font-size: 11px;
  369. color: var(--g300);
  370. letter-spacing: 0.12em;
  371. text-transform: uppercase;
  372. margin-bottom: 6px;
  373. }
  374. .about-callout dd {
  375. font-family: var(--sans);
  376. font-size: 15px;
  377. color: var(--g100);
  378. margin-bottom: 14px;
  379. }
  380. .about-callout dd:last-child { margin-bottom: 0; }
  381. .about-callout a { color: var(--g300); }
  382. .about-callout a:hover { color: var(--g100); }
  383. @media (min-width: 768px) {
  384. .about-grid { grid-template-columns: 1.6fr 1fr; gap: 56px; }
  385. }
  386. /* ── STACK ── */
  387. .stack { background: var(--page); }
  388. .stack-grid {
  389. display: grid;
  390. grid-template-columns: 1fr;
  391. gap: 20px;
  392. margin-top: 40px;
  393. }
  394. .stack-card {
  395. background: #fff;
  396. border: 1px solid var(--rule);
  397. border-radius: var(--r-md);
  398. padding: 24px;
  399. transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  400. }
  401. .stack-card:hover {
  402. border-color: var(--g300);
  403. transform: translateY(-2px);
  404. box-shadow: var(--shadow-md);
  405. }
  406. .stack-card-head {
  407. display: flex;
  408. align-items: baseline;
  409. justify-content: space-between;
  410. margin-bottom: 16px;
  411. padding-bottom: 12px;
  412. border-bottom: 1px dashed var(--rule);
  413. }
  414. .stack-card h3 {
  415. font-family: var(--serif);
  416. font-weight: 600;
  417. font-size: 19px;
  418. color: var(--ink-1);
  419. letter-spacing: -0.01em;
  420. }
  421. .stack-card-tag {
  422. font-family: var(--mono);
  423. font-size: 11px;
  424. color: var(--g500);
  425. letter-spacing: 0.1em;
  426. }
  427. .pills {
  428. display: flex;
  429. flex-wrap: wrap;
  430. gap: 8px;
  431. list-style: none;
  432. }
  433. .pill {
  434. display: inline-block;
  435. font-family: var(--mono);
  436. font-size: 12px;
  437. font-weight: 500;
  438. color: var(--g900);
  439. background: var(--g050);
  440. border: 1px solid var(--g100);
  441. padding: 6px 12px;
  442. border-radius: var(--r-pill);
  443. transition: background .18s ease, border-color .18s ease, color .18s ease;
  444. }
  445. .pill:hover {
  446. background: var(--g100);
  447. border-color: var(--g300);
  448. color: var(--g700);
  449. }
  450. .pill-context {
  451. opacity: 0.65;
  452. font-weight: 400;
  453. margin-left: 3px;
  454. }
  455. .stack-note {
  456. margin-top: 14px;
  457. padding-top: 12px;
  458. border-top: 1px dashed var(--rule);
  459. font-family: var(--mono);
  460. font-size: 12px;
  461. color: var(--ink-3);
  462. letter-spacing: 0.02em;
  463. display: flex;
  464. align-items: center;
  465. gap: 8px;
  466. flex-wrap: wrap;
  467. }
  468. .stack-note code {
  469. font-family: var(--mono);
  470. font-size: 12px;
  471. font-weight: 500;
  472. color: var(--g700);
  473. background: var(--g050);
  474. border: 1px solid var(--g100);
  475. padding: 2px 8px;
  476. border-radius: var(--r-sm);
  477. }
  478. @media (min-width: 768px) { .stack-grid { grid-template-columns: repeat(2, 1fr); } }
  479. @media (min-width: 1200px) { .stack-grid { grid-template-columns: repeat(3, 1fr); } }
  480. /* ── EXPERIENCE ── */
  481. .experience { background: var(--g050); }
  482. .timeline {
  483. position: relative;
  484. margin-top: 40px;
  485. padding-left: 28px;
  486. border-left: 2px solid var(--g100);
  487. }
  488. .timeline-item {
  489. position: relative;
  490. padding: 0 0 36px 24px;
  491. }
  492. .timeline-item:last-child { padding-bottom: 0; }
  493. .timeline-item::before {
  494. content: "";
  495. position: absolute;
  496. left: -34px; top: 6px;
  497. width: 12px; height: 12px;
  498. border-radius: 50%;
  499. background: var(--page);
  500. border: 2px solid var(--g500);
  501. box-shadow: 0 0 0 4px var(--g050);
  502. }
  503. .timeline-item.current::before {
  504. background: var(--g500);
  505. box-shadow: 0 0 0 4px var(--g050), 0 0 0 8px rgba(45,122,79,0.18);
  506. }
  507. .timeline-meta {
  508. display: flex;
  509. flex-wrap: wrap;
  510. align-items: baseline;
  511. gap: 12px;
  512. margin-bottom: 8px;
  513. font-family: var(--mono);
  514. font-size: 12px;
  515. color: var(--ink-3);
  516. letter-spacing: 0.04em;
  517. }
  518. .timeline-meta .period {
  519. color: var(--g700);
  520. font-weight: 600;
  521. }
  522. .timeline-meta .badge {
  523. display: inline-block;
  524. background: var(--g100);
  525. color: var(--g700);
  526. padding: 2px 8px;
  527. border-radius: var(--r-pill);
  528. font-size: 10px;
  529. font-weight: 600;
  530. letter-spacing: 0.08em;
  531. text-transform: uppercase;
  532. }
  533. .timeline-item h3 {
  534. font-family: var(--serif);
  535. font-weight: 600;
  536. font-size: 22px;
  537. color: var(--ink-1);
  538. margin-bottom: 4px;
  539. letter-spacing: -0.01em;
  540. }
  541. .timeline-item h3 a {
  542. color: inherit;
  543. border-bottom: 1px solid transparent;
  544. transition: border-color .18s ease, color .18s ease;
  545. }
  546. .timeline-item h3 a:hover { color: var(--g700); border-color: var(--g500); }
  547. .timeline-role {
  548. font-family: var(--mono);
  549. font-size: 13px;
  550. color: var(--g700);
  551. margin-bottom: 12px;
  552. }
  553. .timeline-desc {
  554. color: var(--ink-2);
  555. line-height: 1.6;
  556. max-width: 64ch;
  557. }
  558. .timeline-contract {
  559. font-family: var(--mono);
  560. font-size: 12px;
  561. color: var(--ink-3);
  562. font-style: italic;
  563. margin-top: -6px;
  564. margin-bottom: 12px;
  565. }
  566. .timeline-intro {
  567. color: var(--ink-2);
  568. line-height: 1.55;
  569. max-width: 64ch;
  570. margin-bottom: 14px;
  571. }
  572. .timeline-bullets {
  573. list-style: none;
  574. display: flex;
  575. flex-direction: column;
  576. gap: 10px;
  577. margin-bottom: 18px;
  578. max-width: 70ch;
  579. }
  580. .timeline-bullets li {
  581. position: relative;
  582. padding-left: 22px;
  583. color: var(--ink-2);
  584. line-height: 1.55;
  585. font-size: 15px;
  586. }
  587. .timeline-bullets li::before {
  588. content: "▸";
  589. position: absolute;
  590. left: 0;
  591. top: 1px;
  592. color: var(--g500);
  593. font-size: 13px;
  594. line-height: 1.55;
  595. }
  596. .timeline-stack {
  597. margin-top: 4px;
  598. }
  599. .timeline-stack .pill {
  600. font-size: 11px;
  601. padding: 4px 10px;
  602. }
  603. /* ── PROJETS ── */
  604. .projets { background: var(--page); }
  605. .projects-grid {
  606. display: grid;
  607. grid-template-columns: 1fr;
  608. gap: 20px;
  609. margin-top: 40px;
  610. }
  611. @media (min-width: 768px) { .projects-grid { grid-template-columns: repeat(2, 1fr); } }
  612. .project-card {
  613. background: #fff;
  614. border: 1px solid var(--rule);
  615. border-radius: var(--r-md);
  616. padding: 24px;
  617. transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  618. display: flex;
  619. flex-direction: column;
  620. }
  621. .project-card:hover {
  622. border-color: var(--g300);
  623. transform: translateY(-2px);
  624. box-shadow: var(--shadow-md);
  625. }
  626. .project-card-head {
  627. display: flex;
  628. align-items: baseline;
  629. justify-content: space-between;
  630. gap: 12px;
  631. margin-bottom: 12px;
  632. padding-bottom: 10px;
  633. border-bottom: 1px dashed var(--rule);
  634. }
  635. .project-card h3 {
  636. font-family: var(--serif);
  637. font-weight: 600;
  638. font-size: 20px;
  639. color: var(--ink-1);
  640. letter-spacing: -0.01em;
  641. }
  642. .project-card-tag {
  643. font-family: var(--mono);
  644. font-size: 11px;
  645. color: var(--g500);
  646. letter-spacing: 0.1em;
  647. flex-shrink: 0;
  648. white-space: nowrap;
  649. }
  650. .project-tagline {
  651. font-family: var(--serif);
  652. font-style: italic;
  653. font-weight: 300;
  654. font-size: 15px;
  655. color: var(--g700);
  656. margin-bottom: 12px;
  657. line-height: 1.4;
  658. }
  659. .project-desc {
  660. color: var(--ink-2);
  661. line-height: 1.6;
  662. font-size: 15px;
  663. margin-bottom: 14px;
  664. }
  665. .project-link {
  666. margin-top: auto;
  667. font-family: var(--mono);
  668. font-size: 13px;
  669. color: var(--g500);
  670. border-bottom: 1px solid transparent;
  671. transition: color .18s ease, border-color .18s ease;
  672. align-self: flex-start;
  673. }
  674. .project-link:hover {
  675. color: var(--g700);
  676. border-bottom-color: var(--g500);
  677. }
  678. /* ── FORMATION ── */
  679. .formation { background: var(--g050); }
  680. .formation .timeline { border-left-color: var(--g100); }
  681. .formation .timeline-item::before { box-shadow: 0 0 0 4px var(--g050); }
  682. .formation-school-desc {
  683. font-family: var(--serif);
  684. font-style: italic;
  685. font-weight: 300;
  686. color: var(--ink-2);
  687. line-height: 1.55;
  688. max-width: 64ch;
  689. margin-bottom: 20px;
  690. }
  691. .formation-themes {
  692. display: grid;
  693. grid-template-columns: 1fr;
  694. gap: 18px;
  695. margin-top: 24px;
  696. }
  697. @media (min-width: 768px) { .formation-themes { grid-template-columns: repeat(2, 1fr); } }
  698. @media (min-width: 1200px) { .formation-themes { grid-template-columns: repeat(3, 1fr); } }
  699. .theme-card {
  700. background: #fff;
  701. border: 1px solid var(--rule);
  702. border-radius: var(--r-md);
  703. padding: 22px;
  704. transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  705. display: flex;
  706. flex-direction: column;
  707. }
  708. .theme-card:hover {
  709. border-color: var(--g300);
  710. transform: translateY(-2px);
  711. box-shadow: var(--shadow-md);
  712. }
  713. .theme-card-head {
  714. display: flex;
  715. align-items: baseline;
  716. justify-content: space-between;
  717. gap: 12px;
  718. margin-bottom: 12px;
  719. padding-bottom: 10px;
  720. border-bottom: 1px dashed var(--rule);
  721. }
  722. .theme-card h4 {
  723. font-family: var(--serif);
  724. font-weight: 600;
  725. font-size: 18px;
  726. color: var(--ink-1);
  727. letter-spacing: -0.01em;
  728. line-height: 1.2;
  729. }
  730. .theme-card-tag {
  731. font-family: var(--mono);
  732. font-size: 11px;
  733. color: var(--g500);
  734. letter-spacing: 0.1em;
  735. flex-shrink: 0;
  736. }
  737. .theme-quote {
  738. font-family: var(--serif);
  739. font-style: italic;
  740. font-weight: 300;
  741. color: var(--ink-2);
  742. font-size: 14px;
  743. line-height: 1.5;
  744. padding-left: 12px;
  745. border-left: 2px solid var(--g500);
  746. margin-bottom: 16px;
  747. }
  748. .theme-list {
  749. list-style: none;
  750. display: flex;
  751. flex-direction: column;
  752. gap: 10px;
  753. }
  754. .theme-list li {
  755. font-size: 13.5px;
  756. line-height: 1.55;
  757. color: var(--ink-2);
  758. }
  759. .theme-list code {
  760. font-family: var(--mono);
  761. font-size: 12px;
  762. font-weight: 500;
  763. color: var(--g700);
  764. background: var(--g050);
  765. border: 1px solid var(--g100);
  766. padding: 1px 7px;
  767. border-radius: var(--r-sm);
  768. }
  769. .formation-tsrit-list {
  770. list-style: none;
  771. display: flex;
  772. flex-direction: column;
  773. gap: 10px;
  774. margin-top: 12px;
  775. max-width: 64ch;
  776. }
  777. .formation-tsrit-list li {
  778. color: var(--ink-2);
  779. line-height: 1.55;
  780. padding-left: 18px;
  781. position: relative;
  782. }
  783. .formation-tsrit-list li::before {
  784. content: "";
  785. position: absolute;
  786. left: 0; top: 0.65em;
  787. width: 8px; height: 1px;
  788. background: var(--g500);
  789. }
  790. .formation-tsrit-list li strong { color: var(--ink-1); font-weight: 600; }
  791. .honors {
  792. display: inline-flex;
  793. align-items: center;
  794. gap: 8px;
  795. font-family: var(--mono);
  796. font-size: 12px;
  797. font-weight: 600;
  798. color: var(--g700);
  799. background: var(--g100);
  800. border: 1px solid var(--g300);
  801. padding: 6px 14px;
  802. border-radius: var(--r-pill);
  803. letter-spacing: 0.04em;
  804. margin: 4px 0 14px;
  805. }
  806. .honors::before {
  807. content: "★";
  808. color: var(--g500);
  809. font-size: 13px;
  810. }
  811. /* ── MÉTHODE ── */
  812. .methode { background: var(--page); }
  813. .methode-list {
  814. list-style: none;
  815. display: grid;
  816. grid-template-columns: 1fr;
  817. gap: 16px;
  818. margin-top: 40px;
  819. max-width: 820px;
  820. }
  821. .methode-item {
  822. display: grid;
  823. grid-template-columns: 56px 1fr;
  824. gap: 20px;
  825. align-items: start;
  826. background: #fff;
  827. border: 1px solid var(--rule);
  828. border-radius: var(--r-md);
  829. padding: 22px 24px;
  830. transition: border-color .25s ease, transform .25s ease, box-shadow .25s ease;
  831. }
  832. .methode-item:hover {
  833. border-color: var(--g300);
  834. transform: translateY(-2px);
  835. box-shadow: var(--shadow-md);
  836. }
  837. .methode-num {
  838. font-family: var(--mono);
  839. font-size: 22px;
  840. font-weight: 700;
  841. color: var(--g500);
  842. letter-spacing: -0.02em;
  843. line-height: 1;
  844. padding-top: 4px;
  845. }
  846. .methode-body h3 {
  847. font-family: var(--serif);
  848. font-weight: 600;
  849. font-size: 19px;
  850. color: var(--ink-1);
  851. letter-spacing: -0.01em;
  852. margin-bottom: 6px;
  853. line-height: 1.25;
  854. }
  855. .methode-body p {
  856. color: var(--ink-2);
  857. line-height: 1.6;
  858. font-size: 15px;
  859. max-width: 64ch;
  860. }
  861. @media (max-width: 640px) {
  862. .methode-item { grid-template-columns: 1fr; gap: 8px; padding: 20px; }
  863. .methode-num { font-size: 18px; padding-top: 0; }
  864. }
  865. /* ── CONTACT ── */
  866. .contact {
  867. background: var(--dark);
  868. color: #fff;
  869. position: relative;
  870. overflow: hidden;
  871. }
  872. .contact::after {
  873. content: "";
  874. position: absolute;
  875. right: -120px; bottom: -120px;
  876. width: 360px; height: 360px;
  877. border-radius: 50%;
  878. background: radial-gradient(circle, rgba(45,122,79,0.18) 0%, transparent 70%);
  879. pointer-events: none;
  880. }
  881. .contact-grid {
  882. display: grid;
  883. grid-template-columns: 1fr;
  884. gap: 32px;
  885. position: relative;
  886. z-index: 1;
  887. }
  888. .contact-list {
  889. list-style: none;
  890. display: grid;
  891. grid-template-columns: 1fr;
  892. gap: 12px;
  893. margin-top: 32px;
  894. }
  895. .contact-row {
  896. display: grid;
  897. grid-template-columns: 28px 1fr;
  898. gap: 18px;
  899. align-items: center;
  900. padding: 18px 20px;
  901. background: rgba(255, 255, 255, 0.04);
  902. border: 1px solid rgba(106,185,138,0.18);
  903. border-radius: var(--r-md);
  904. transition: border-color .18s ease, background .18s ease, transform .18s ease;
  905. color: var(--g100);
  906. }
  907. .contact-row:hover {
  908. border-color: var(--g300);
  909. background: rgba(106,185,138,0.08);
  910. transform: translateY(-1px);
  911. color: #fff;
  912. }
  913. .contact-row svg { width: 20px; height: 20px; color: var(--g300); flex-shrink: 0; }
  914. .contact-row .label {
  915. display: block;
  916. font-family: var(--mono);
  917. font-size: 11px;
  918. color: var(--g300);
  919. letter-spacing: 0.12em;
  920. text-transform: uppercase;
  921. margin-bottom: 2px;
  922. }
  923. .contact-row .value {
  924. font-family: var(--mono);
  925. font-size: 15px;
  926. color: #fff;
  927. font-weight: 500;
  928. word-break: break-word;
  929. }
  930. @media (min-width: 768px) {
  931. .contact-list { grid-template-columns: repeat(2, 1fr); }
  932. }
  933. /* ── FOOTER ── */
  934. .footer {
  935. background: #061008;
  936. color: rgba(223, 240, 231, 0.55);
  937. padding: 32px 24px;
  938. border-top: 1px solid rgba(106,185,138,0.1);
  939. }
  940. .footer-inner {
  941. max-width: var(--max-w);
  942. margin: 0 auto;
  943. display: flex;
  944. flex-wrap: wrap;
  945. gap: 16px 32px;
  946. justify-content: space-between;
  947. align-items: center;
  948. font-family: var(--mono);
  949. font-size: 12px;
  950. letter-spacing: 0.04em;
  951. }
  952. .footer a { color: var(--g300); }
  953. .footer a:hover { color: var(--g100); }
  954. .footer-links { display: flex; gap: 20px; flex-wrap: wrap; }
  955. /* ── RESPONSIVE TWEAKS ── */
  956. @media (max-width: 768px) {
  957. section { padding: 72px 20px; }
  958. .hero { padding: 56px 20px 72px; }
  959. .hero-cta .btn { flex: 1 1 auto; justify-content: center; }
  960. .timeline { padding-left: 22px; }
  961. .timeline-item { padding-left: 18px; }
  962. .timeline-item::before { left: -29px; }
  963. }
  964. @media (min-width: 1200px) {
  965. section { padding: 120px 24px; }
  966. }
  967. </style>
  968. </head>
  969. <body>
  970. <!-- NAV -->
  971. <header class="nav" role="banner">
  972. <div class="nav-inner">
  973. <a href="#hero" class="brand" aria-label="Bastien Chanot — accueil">bchanot.fr</a>
  974. <button class="nav-toggle" type="button" aria-label="Ouvrir le menu" aria-expanded="false" aria-controls="primary-nav">
  975. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
  976. </button>
  977. <nav aria-label="Navigation principale">
  978. <ul id="primary-nav" class="nav-links">
  979. <li><a href="#about">À propos</a></li>
  980. <li><a href="#stack">Stack</a></li>
  981. <li><a href="#experience">Parcours</a></li>
  982. <li><a href="#projets">Projets</a></li>
  983. <li><a href="#formation">Formation</a></li>
  984. <li><a href="#methode">Méthode</a></li>
  985. <li><a href="#contact">Contact</a></li>
  986. </ul>
  987. </nav>
  988. </div>
  989. </header>
  990. <main>
  991. <!-- HERO -->
  992. <section id="hero" class="hero" aria-labelledby="hero-name">
  993. <div class="hero-inner">
  994. <p class="hero-eyebrow reveal">Disponible — CDI systèmes&nbsp;/&nbsp;embarqué · missions freelance</p>
  995. <h1 id="hero-name" class="hero-name reveal d1">Bastien&nbsp;<em>Chanot</em></h1>
  996. <p class="hero-title reveal d2">Développeur Systèmes<span class="sep">·</span>Embarqué<span class="sep">·</span>Backend</p>
  997. <p class="hero-tagline reveal d3">Du kernel Linux au backend Rust — 7 ans de développement systèmes en production.</p>
  998. <div class="hero-cta reveal d4">
  999. <a class="btn btn-primary" href="#contact">
  1000. Me contacter
  1001. <svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="19" x2="19" y2="5"/><polyline points="8 5 19 5 19 16"/></svg>
  1002. </a>
  1003. <a class="btn btn-secondary" href="CV_Bastien_Chanot.html">
  1004. Voir le CV
  1005. <svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="19" x2="19" y2="5"/><polyline points="8 5 19 5 19 16"/></svg>
  1006. </a>
  1007. <a class="btn btn-secondary" href="CV_Bastien_Chanot.pdf" download>
  1008. Télécharger PDF
  1009. <svg class="arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
  1010. </a>
  1011. </div>
  1012. <div class="hero-meta reveal d5">
  1013. <span><span class="dot"></span>C · Rust · Linux Kernel</span>
  1014. <span><span class="dot"></span>AOSP · Embarqué</span>
  1015. <span><span class="dot"></span>Backend · Cloud</span>
  1016. </div>
  1017. </div>
  1018. </section>
  1019. <!-- ABOUT -->
  1020. <section id="about" class="about section-dark" aria-labelledby="about-title">
  1021. <div class="container">
  1022. <span class="section-label">À propos</span>
  1023. <h2 id="about-title" class="section-title">Sept ans à écrire du code qui tourne là où ça compte.</h2>
  1024. <div class="about-grid">
  1025. <div class="about-text">
  1026. <p>Je suis développeur systèmes senior, formé à l'<strong>École&nbsp;42</strong> et passé par six ans chez <strong>CareGame</strong> où j'ai écrit des drivers Linux kernel, un backend Rust temps réel et fait tourner des serveurs GPU bare-metal en production.</p>
  1027. <p>Mon terrain de jeu : <strong>C, Rust, Linux kernel, AOSP, embarqué, infrastructure</strong>. Quand un problème touche au bas niveau — port matériel, latence, sécurité, kernel — c'est là que j'apporte le plus de valeur.</p>
  1028. <p>Ce qui m'intéresse, c'est descendre jusqu'à ce qu'il n'y ait plus de magie — <strong>kernel, hardware, drivers</strong>. Là, soit ça marche, soit ça ne marche pas.</p>
  1029. <p>C'est ce confort-là que je cherche dans une équipe : <strong>systèmes, embarqué, backend bas niveau</strong>, sur une stack dont on peut lire le code source. Pas envie d'aller vers le buzzword-driven — microservices à tout prix, framework du mois, archi conçue pour le pitch deck.</p>
  1030. <p>Aujourd'hui indépendant sous la marque <strong>ZenQuality</strong>, mais avant tout en recherche d'un <strong>CDI en systèmes embarqués ou logiciel</strong> — les missions freelance se font en parallèle.</p>
  1031. <p>Côté présence : <strong>full remote</strong> idéalement, ou <strong>hybride 1 à 2 jours par mois</strong> si l'équipe est à Paris. Mobilité visée à moyen terme : <strong>Pays de la Loire</strong>.</p>
  1032. </div>
  1033. <dl class="about-callout">
  1034. <dt>Recherche prioritaire</dt>
  1035. <dd>CDI systèmes embarqués / logiciel</dd>
  1036. <dt>En parallèle</dt>
  1037. <dd>Missions freelance · ZenQuality</dd>
  1038. <dt>Localisation actuelle</dt>
  1039. <dd>Yerres (91) · mobilité Pays de la Loire</dd>
  1040. <dt>Présence</dt>
  1041. <dd>Full remote · ou 1–2 j/mois si Paris</dd>
  1042. <dt>Site pro</dt>
  1043. <dd><a href="https://zenquality.fr" target="_blank" rel="noopener">zenquality.fr&nbsp;↗</a></dd>
  1044. </dl>
  1045. </div>
  1046. </div>
  1047. </section>
  1048. <!-- STACK -->
  1049. <section id="stack" class="stack" aria-labelledby="stack-title">
  1050. <div class="container">
  1051. <span class="section-label">Stack technique</span>
  1052. <h2 id="stack-title" class="section-title">Ce avec quoi je travaille, sans le marketing.</h2>
  1053. <p class="section-intro">Outils éprouvés, choisis pour leurs garanties — pas pour leur hype. Tout ce qui suit est en production ou l'a été.</p>
  1054. <div class="stack-grid">
  1055. <article class="stack-card">
  1056. <header class="stack-card-head">
  1057. <h3>Langages</h3>
  1058. <span class="stack-card-tag">// 01</span>
  1059. </header>
  1060. <ul class="pills">
  1061. <li class="pill">C</li>
  1062. <li class="pill">Rust</li>
  1063. <li class="pill">Bash</li>
  1064. <li class="pill">Python</li>
  1065. <li class="pill">Java<span class="pill-context">(AOSP/Android)</span></li>
  1066. </ul>
  1067. <p class="stack-note">Familier avec&nbsp;: <code>C++</code></p>
  1068. </article>
  1069. <article class="stack-card">
  1070. <header class="stack-card-head">
  1071. <h3>Embarqué</h3>
  1072. <span class="stack-card-tag">// 02</span>
  1073. </header>
  1074. <ul class="pills">
  1075. <li class="pill">Linux kernel drivers</li>
  1076. <li class="pill">AOSP</li>
  1077. <li class="pill">ARM / x86</li>
  1078. <li class="pill">GPIO</li>
  1079. <li class="pill">NFC</li>
  1080. <li class="pill">ESC/POS</li>
  1081. <li class="pill">cross-compilation GCC</li>
  1082. </ul>
  1083. </article>
  1084. <article class="stack-card">
  1085. <header class="stack-card-head">
  1086. <h3>Conteneurs</h3>
  1087. <span class="stack-card-tag">// 03</span>
  1088. </header>
  1089. <ul class="pills">
  1090. <li class="pill">Docker</li>
  1091. <li class="pill">LXC / LXD</li>
  1092. <li class="pill">QEMU</li>
  1093. <li class="pill">cgroups</li>
  1094. <li class="pill">namespaces</li>
  1095. </ul>
  1096. </article>
  1097. <article class="stack-card">
  1098. <header class="stack-card-head">
  1099. <h3>Backend</h3>
  1100. <span class="stack-card-tag">// 04</span>
  1101. </header>
  1102. <ul class="pills">
  1103. <li class="pill">Rust</li>
  1104. <li class="pill">WebSocket</li>
  1105. <li class="pill">GPU bare-metal</li>
  1106. <li class="pill">ramdisk I/O</li>
  1107. </ul>
  1108. </article>
  1109. <article class="stack-card">
  1110. <header class="stack-card-head">
  1111. <h3>Systèmes</h3>
  1112. <span class="stack-card-tag">// 05</span>
  1113. </header>
  1114. <ul class="pills">
  1115. <li class="pill">Linux bare-metal</li>
  1116. <li class="pill">AOSP</li>
  1117. <li class="pill">Android Backup</li>
  1118. <li class="pill">systemd</li>
  1119. <li class="pill">SELinux</li>
  1120. </ul>
  1121. </article>
  1122. <article class="stack-card">
  1123. <header class="stack-card-head">
  1124. <h3>Cloud / Infra</h3>
  1125. <span class="stack-card-tag">// 06</span>
  1126. </header>
  1127. <ul class="pills">
  1128. <li class="pill">AWS EC2</li>
  1129. <li class="pill">AWS g4dn bare-metal</li>
  1130. <li class="pill">IAM</li>
  1131. <li class="pill">S3</li>
  1132. <li class="pill">CloudWatch</li>
  1133. <li class="pill">Scaleway VPS</li>
  1134. <li class="pill">OVH / Hetzner</li>
  1135. <li class="pill">Nginx</li>
  1136. <li class="pill">Apache</li>
  1137. <li class="pill">Let's Encrypt</li>
  1138. </ul>
  1139. </article>
  1140. <article class="stack-card">
  1141. <header class="stack-card-head">
  1142. <h3>DevOps</h3>
  1143. <span class="stack-card-tag">// 07</span>
  1144. </header>
  1145. <ul class="pills">
  1146. <li class="pill">Git</li>
  1147. <li class="pill">GitHub Actions</li>
  1148. <li class="pill">GitLab</li>
  1149. <li class="pill">CI/CD</li>
  1150. </ul>
  1151. </article>
  1152. <article class="stack-card">
  1153. <header class="stack-card-head">
  1154. <h3>IA / Outils</h3>
  1155. <span class="stack-card-tag">// 08</span>
  1156. </header>
  1157. <ul class="pills">
  1158. <li class="pill">Claude Code (agents/skills custom)</li>
  1159. <li class="pill">N8N</li>
  1160. <li class="pill">automatisation</li>
  1161. </ul>
  1162. </article>
  1163. </div>
  1164. </div>
  1165. </section>
  1166. <!-- EXPERIENCE -->
  1167. <section id="experience" class="experience" aria-labelledby="experience-title">
  1168. <div class="container">
  1169. <span class="section-label">Parcours</span>
  1170. <h2 id="experience-title" class="section-title">Trois expériences qui résument l'essentiel.</h2>
  1171. <p class="section-intro">Sept ans de développement systèmes en production — du kernel au backend, de la puce au serveur.</p>
  1172. <ol class="timeline">
  1173. <li class="timeline-item current">
  1174. <div class="timeline-meta">
  1175. <span class="period">avr.&nbsp;2026 — présent</span>
  1176. <span class="badge">En cours</span>
  1177. <span>Yerres · Full remote</span>
  1178. </div>
  1179. <h3><a href="https://zenquality.fr" target="_blank" rel="noopener">ZenQuality</a></h3>
  1180. <p class="timeline-role">Développeur indépendant · Systèmes &amp; Backend</p>
  1181. <p class="timeline-intro">Indépendant systèmes / embarqué / backend. En recherche prioritaire d'un CDI en parallèle.</p>
  1182. <ul class="timeline-bullets">
  1183. <li>Mission SEO et conformité légale RGPD pour PME service (Île-de-France) — audit technique Core Web Vitals + Schema.org + NAP, refonte CGV B2B/B2C, RGPD, mentions légales, médiateur CM2C. Plan d'action 12 sprints.</li>
  1184. <li>Site vitrine WordPress (Gutenverse) pour PME esthétique — conception, intégration, déploiement et support continu (hébergement client).</li>
  1185. <li>Setup et auto-hébergement de l'infra ZenQuality sur VPS Scaleway — stack Astro / React / PHP 8 / PostgreSQL conteneurisée Docker, déploiement automatisé, pipeline de production complet.</li>
  1186. </ul>
  1187. <ul class="pills timeline-stack">
  1188. <li class="pill">Astro</li>
  1189. <li class="pill">React</li>
  1190. <li class="pill">PHP 8</li>
  1191. <li class="pill">PostgreSQL</li>
  1192. <li class="pill">Docker</li>
  1193. <li class="pill">Scaleway VPS</li>
  1194. <li class="pill">WordPress / Gutenverse</li>
  1195. <li class="pill">SEO</li>
  1196. <li class="pill">RGPD</li>
  1197. </ul>
  1198. </li>
  1199. <li class="timeline-item">
  1200. <div class="timeline-meta">
  1201. <span class="period">mars&nbsp;2019 — mars&nbsp;2025</span>
  1202. <span>Paris · Full remote dès 2020</span>
  1203. </div>
  1204. <h3>CareGame</h3>
  1205. <p class="timeline-role">Développeur logiciel · Systèmes &amp; Backend</p>
  1206. <p class="timeline-intro">Plateforme de cloud gaming en production : fleet GPU bare-metal AWS g4dn, conteneurs AOSP, backend Rust temps réel. Plusieurs centaines de joueurs servis simultanément.</p>
  1207. <ul class="timeline-bullets">
  1208. <li>Conception et maintenance de modules kernel Linux en C (x86 / ARM) — drivers d'interface hôte / conteneur (Linux → AOSP), en interface avec les équipes infra et produit.</li>
  1209. <li>Conception de l'isolation CPU/GPU par session — adaptation de modules GPU Nvidia, partitionnement 2 cœurs/session, sérialisation des accès concurrents sur zones GPU partagées. Résultat : 32 sessions AAA stables par serveur.</li>
  1210. <li>Co-développement du backend Rust orchestrant le cycle de vie des conteneurs AOSP — WebSocket temps réel clients ↔ instances, intégration Docker + LXC, scheduling des sessions sur la fleet GPU.</li>
  1211. <li>Développement de virtual input devices AOSP en Java (touchscreen, gamepad) — pipeline complet inputs frontend → backend Rust → drivers hôtes → injection AOSP, optimisé latence temps réel gameplay AAA.</li>
  1212. <li>Architecture et exploitation de fleet GPU bare-metal AWS g4dn.metal (8× GPU T4, 64 vCPU, ~20 serveurs en pic) — isolation 2 cœurs CPU/session, ramdisk I/O, 32 sessions AAA simultanées/serveur. Plusieurs centaines de joueurs servis en parallèle (Asphalt 9 : 3 sessions/T4).</li>
  1213. <li>Reprise et hardening d'un PoC LXD + Docker issu d'une R&amp;D Nvidia (intégration côté Docker principalement) — adaptation production cloud gaming, débogage kernel/conteneur, performance validée par les équipes Nvidia comme dépassant le scope initial du PoC.</li>
  1214. <li>Collaboration technique directe en anglais avec Canonical (Anbox + builds LXC/LXD non commerciaux, remontée bugs et feature requests) et Ampere Computing (intégration et benchmark de serveurs ARM pré-commerciaux pour évaluation de migration de fleet).</li>
  1215. <li>Pipeline d'installation automatique de jeux AOSP et persistance des sauvegardes utilisateur — fusion Android Backup natif + scripts custom pour cas non gérés nativement (DRM, données externes).</li>
  1216. <li>Développement d'un outil d'orchestration Bash modulaire (1000+ lignes) — parsing avancé arguments Docker, préparation et lancement automatisé conteneurs AOSP, brique appelée par la CI et le backend Rust.</li>
  1217. </ul>
  1218. <ul class="pills timeline-stack">
  1219. <li class="pill">C</li>
  1220. <li class="pill">Rust</li>
  1221. <li class="pill">Java</li>
  1222. <li class="pill">Bash</li>
  1223. <li class="pill">Linux kernel</li>
  1224. <li class="pill">AOSP</li>
  1225. <li class="pill">Docker</li>
  1226. <li class="pill">LXC / LXD</li>
  1227. <li class="pill">AWS g4dn.metal</li>
  1228. <li class="pill">WebSocket</li>
  1229. <li class="pill">Nvidia GPU T4</li>
  1230. </ul>
  1231. </li>
  1232. <li class="timeline-item">
  1233. <div class="timeline-meta">
  1234. <span class="period">fév.&nbsp;2017 — nov.&nbsp;2017</span>
  1235. <span>Ivry-sur-Seine</span>
  1236. </div>
  1237. <h3>Deewee</h3>
  1238. <p class="timeline-role">Développeur C · Système embarqué</p>
  1239. <p class="timeline-contract">Stage 42 (6 mois) puis CDD (4 mois)</p>
  1240. <p class="timeline-intro">Boîtier connecté pour interception du flux d'une imprimante thermique.</p>
  1241. <ul class="timeline-bullets">
  1242. <li>Développement du logiciel embarqué en C pour boîtier connecté basé Orange Pi (Debian ARM) — interception du flux ESC/POS d'une imprimante thermique, génération PNG du ticket, transfert WiFi direct vers application mobile à la connexion.</li>
  1243. <li>Intégration matérielle : GPIO physique (bouton + timeout), hotspot WiFi embarqué avec diffusion des credentials via NFC pour appairage automatique.</li>
  1244. </ul>
  1245. <ul class="pills timeline-stack">
  1246. <li class="pill">C</li>
  1247. <li class="pill">Debian ARM</li>
  1248. <li class="pill">Orange Pi</li>
  1249. <li class="pill">ESC/POS</li>
  1250. <li class="pill">GPIO</li>
  1251. <li class="pill">NFC</li>
  1252. <li class="pill">WiFi</li>
  1253. </ul>
  1254. </li>
  1255. </ol>
  1256. </div>
  1257. </section>
  1258. <!-- PROJETS -->
  1259. <section id="projets" class="projets" aria-labelledby="projets-title">
  1260. <div class="container">
  1261. <span class="section-label">Projets</span>
  1262. <h2 id="projets-title" class="section-title">Ce que je fais à côté.</h2>
  1263. <p class="section-intro">Infra perso et code public — l'environnement où je teste, casse, documente, et reprends.</p>
  1264. <div class="projects-grid">
  1265. <article class="project-card">
  1266. <header class="project-card-head">
  1267. <h3>Code source &amp; projets persos</h3>
  1268. <span class="project-card-tag">en continu</span>
  1269. </header>
  1270. <p class="project-tagline">Serveur Git auto-hébergé en production.</p>
  1271. <p class="project-desc">Configuration Claude Code, dotfiles, projets bas-niveau (42, expérimentations C/Rust) — accessibles publiquement. Mirror automatique vers GitHub via push hook.</p>
  1272. <a class="project-link" href="https://git.bchanot.fr/bchanot" target="_blank" rel="noopener">git.bchanot.fr/bchanot&nbsp;↗</a>
  1273. </article>
  1274. <article class="project-card">
  1275. <header class="project-card-head">
  1276. <h3>Homelab</h3>
  1277. <span class="project-card-tag">en continu</span>
  1278. </header>
  1279. <p class="project-tagline">Infrastructure personnelle.</p>
  1280. <p class="project-desc">Auto-hébergement Git (Gogs) / DNS / VPN / SMB — NAS Asustor, Freebox WireGuard VPN site-to-site, Pi-hole, segmentation réseau, hardening fail2ban, gocryptfs sur dossiers sensibles.</p>
  1281. </article>
  1282. </div>
  1283. </div>
  1284. </section>
  1285. <!-- FORMATION -->
  1286. <section id="formation" class="formation" aria-labelledby="formation-title">
  1287. <div class="container">
  1288. <span class="section-label">Formation</span>
  1289. <h2 id="formation-title" class="section-title">Deux écoles, un fil rouge : le bas niveau.</h2>
  1290. <p class="section-intro">Le socle technique derrière sept ans de production.</p>
  1291. <ol class="timeline">
  1292. <li class="timeline-item">
  1293. <div class="timeline-meta">
  1294. <span class="period">2015 — 2019</span>
  1295. <span>Clichy</span>
  1296. </div>
  1297. <h3>École 42</h3>
  1298. <p class="timeline-role">Cursus en informatique fondamentale</p>
  1299. <p class="formation-school-desc">Kernel, mémoire, shell, sécurité — recoder pour comprendre.</p>
  1300. <div class="formation-themes">
  1301. <article class="theme-card">
  1302. <header class="theme-card-head">
  1303. <h4>Systèmes &amp; Kernel</h4>
  1304. <span class="theme-card-tag">// 01</span>
  1305. </header>
  1306. <p class="theme-quote">Bootstrap d'OS, drivers, gestion matérielle, allocation mémoire.</p>
  1307. <ul class="theme-list">
  1308. <li><code>ft_linux</code> &amp; <code>kfs-1</code> — Linux From Scratch et noyau minimaliste : bootloader ASM, GDT, interruptions, driver char device clavier mappé.</li>
  1309. <li><code>drivers &amp; interrupt</code> — drivers kernel Linux et gestion d'interruptions niveau noyau.</li>
  1310. <li><code>process &amp; memory</code> — modèle de processus Unix, gestion mémoire kernel.</li>
  1311. <li><code>little penguin</code> — contribution kernel Linux : style guide, patch submission, contrib upstream.</li>
  1312. <li><code>malloc</code> — allocateur mémoire complet (libft_malloc.so) avec mmap, zones tiny / small / large.</li>
  1313. </ul>
  1314. </article>
  1315. <article class="theme-card">
  1316. <header class="theme-card-head">
  1317. <h4>Bas niveau &amp; Outils système</h4>
  1318. <span class="theme-card-tag">// 02</span>
  1319. </header>
  1320. <p class="theme-quote">Recoder les outils qu'on utilise tous les jours pour comprendre vraiment ce qu'ils font.</p>
  1321. <ul class="theme-list">
  1322. <li><code>nm</code> — parsing d'exécutables ELF, tables de symboles.</li>
  1323. <li><code>42sh</code> / <code>21</code> — shell POSIX complet : parser, redirections, jobs, history, autocomplétion.</li>
  1324. <li><code>ft_ls</code> — réimplémentation <code>ls</code> avec options POSIX, permissions, tri, formats.</li>
  1325. <li><code>ft_select</code> — TUI custom avec gestion termios, signaux, redessin partiel.</li>
  1326. </ul>
  1327. </article>
  1328. <article class="theme-card">
  1329. <header class="theme-card-head">
  1330. <h4>Sécurité &amp; Algorithmie</h4>
  1331. <span class="theme-card-tag">// 03</span>
  1332. </header>
  1333. <p class="theme-quote">Comprendre comment un système peut être cassé pour savoir le sécuriser.</p>
  1334. <ul class="theme-list">
  1335. <li><code>snow crash</code> — wargame exploitation système : escalation de privilèges, stack overflow, format string, race conditions.</li>
  1336. <li><code>doctor quine</code> — programme auto-réplicatif (métaprogrammation).</li>
  1337. <li><code>ft_ssl_md5</code> — réimplémentation MD5, SHA-256, base64.</li>
  1338. <li><code>lem-in</code>, <code>push-swap</code> — algorithmique : pathfinding (Edmonds-Karp), optimisation de tri sous contrainte.</li>
  1339. </ul>
  1340. </article>
  1341. </div>
  1342. </li>
  1343. <li class="timeline-item">
  1344. <div class="timeline-meta">
  1345. <span class="period">2013 — 2015</span>
  1346. <span>Vincennes</span>
  1347. </div>
  1348. <h3>TSRIT — Next Formation</h3>
  1349. <p class="timeline-role">BTS Technicien Supérieur Réseaux Informatiques &amp; Télécoms</p>
  1350. <span class="honors">Félicitations du jury</span>
  1351. <p class="timeline-desc">Le socle réseau et infrastructure derrière les compétences systèmes.</p>
  1352. <ul class="formation-tsrit-list">
  1353. <li>Architecture réseau (<strong>OSI</strong>, <strong>TCP/IP</strong>), routage, commutation.</li>
  1354. <li>Administration <strong>Linux</strong> / <strong>Windows Server</strong>, sécurité réseau, virtualisation.</li>
  1355. </ul>
  1356. </li>
  1357. </ol>
  1358. </div>
  1359. </section>
  1360. <!-- MÉTHODE -->
  1361. <section id="methode" class="methode" aria-labelledby="methode-title">
  1362. <div class="container">
  1363. <span class="section-label">Méthode</span>
  1364. <h2 id="methode-title" class="section-title">Façon de travailler.</h2>
  1365. <p class="section-intro">Cinq habitudes héritées de sept ans en prod — pas un manifeste, des réflexes.</p>
  1366. <ol class="methode-list">
  1367. <li class="methode-item">
  1368. <span class="methode-num">01</span>
  1369. <div class="methode-body">
  1370. <h3>Comprendre avant d'écrire.</h3>
  1371. <p>Si je n'arrive pas à expliquer comment un système se comporte, je ne touche pas au code.</p>
  1372. </div>
  1373. </li>
  1374. <li class="methode-item">
  1375. <span class="methode-num">02</span>
  1376. <div class="methode-body">
  1377. <h3>Solutions éprouvées &gt; hype.</h3>
  1378. <p>Choix techniques défendus sur leurs garanties (perf, lisibilité, maintenabilité), pas sur leur buzz.</p>
  1379. </div>
  1380. </li>
  1381. <li class="methode-item">
  1382. <span class="methode-num">03</span>
  1383. <div class="methode-body">
  1384. <h3>Autonome sur la décomposition technique.</h3>
  1385. <p>En interface directe avec les équipes produit, infra et stakeholders externes quand ça compte.</p>
  1386. </div>
  1387. </li>
  1388. <li class="methode-item">
  1389. <span class="methode-num">04</span>
  1390. <div class="methode-body">
  1391. <h3>Trace écrite par défaut.</h3>
  1392. <p>Décisions, post-mortems, docs internes. Le code qui n'est pas documenté est un code qui sera réécrit dans 6 mois.</p>
  1393. </div>
  1394. </li>
  1395. <li class="methode-item">
  1396. <span class="methode-num">05</span>
  1397. <div class="methode-body">
  1398. <h3>Anglais ou français.</h3>
  1399. <p>Communication aussi bien en anglais (Nvidia, Canonical, Ampere) qu'en français — peu importe, je m'adapte à l'équipe.</p>
  1400. </div>
  1401. </li>
  1402. </ol>
  1403. </div>
  1404. </section>
  1405. <!-- CONTACT -->
  1406. <section id="contact" class="contact section-dark" aria-labelledby="contact-title">
  1407. <div class="container">
  1408. <span class="section-label">Contact</span>
  1409. <h2 id="contact-title" class="section-title">Une mission, une question technique, un&nbsp;projet&nbsp;?</h2>
  1410. <p class="section-intro">Le plus simple : l'email. Réponse sous 48&nbsp;h ouvrées.</p>
  1411. <div class="contact-grid">
  1412. <ul class="contact-list">
  1413. <li>
  1414. <a class="contact-row" href="mailto:bastien@bchanot.fr">
  1415. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="5" width="18" height="14" rx="2"/><polyline points="3 7 12 13 21 7"/></svg>
  1416. <span>
  1417. <span class="label">Email</span>
  1418. <span class="value">bastien@bchanot.fr</span>
  1419. </span>
  1420. </a>
  1421. </li>
  1422. <li>
  1423. <a class="contact-row" href="tel:+33778822297">
  1424. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.86 19.86 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6A19.86 19.86 0 0 1 2.12 4.18 2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.72 2.8a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.9.35 1.84.59 2.8.72A2 2 0 0 1 22 16.92z"/></svg>
  1425. <span>
  1426. <span class="label">Téléphone</span>
  1427. <span class="value">+33 7 78 82 22 97</span>
  1428. </span>
  1429. </a>
  1430. </li>
  1431. <li>
  1432. <a class="contact-row" href="https://zenquality.fr" target="_blank" rel="noopener">
  1433. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
  1434. <span>
  1435. <span class="label">Site pro</span>
  1436. <span class="value">zenquality.fr</span>
  1437. </span>
  1438. </a>
  1439. </li>
  1440. <li>
  1441. <a class="contact-row" href="CV_Bastien_Chanot.pdf" download>
  1442. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
  1443. <span>
  1444. <span class="label">CV</span>
  1445. <span class="value">Télécharger le PDF</span>
  1446. </span>
  1447. </a>
  1448. </li>
  1449. </ul>
  1450. </div>
  1451. </div>
  1452. </section>
  1453. </main>
  1454. <!-- FOOTER -->
  1455. <footer class="footer" role="contentinfo">
  1456. <div class="footer-inner">
  1457. <span>© 2026 · Bastien Chanot · bchanot.fr</span>
  1458. <div class="footer-links">
  1459. <a href="CV_Bastien_Chanot.html">CV (HTML)</a>
  1460. <a href="CV_Bastien_Chanot.pdf" download>CV (PDF)</a>
  1461. <a href="https://zenquality.fr" target="_blank" rel="noopener">zenquality.fr ↗</a>
  1462. </div>
  1463. </div>
  1464. </footer>
  1465. <script>
  1466. // Mobile nav toggle
  1467. (function () {
  1468. const toggle = document.querySelector('.nav-toggle');
  1469. const links = document.getElementById('primary-nav');
  1470. if (!toggle || !links) return;
  1471. toggle.addEventListener('click', () => {
  1472. const open = links.classList.toggle('open');
  1473. toggle.setAttribute('aria-expanded', String(open));
  1474. toggle.setAttribute('aria-label', open ? 'Fermer le menu' : 'Ouvrir le menu');
  1475. });
  1476. links.addEventListener('click', (e) => {
  1477. if (e.target instanceof HTMLAnchorElement && links.classList.contains('open')) {
  1478. links.classList.remove('open');
  1479. toggle.setAttribute('aria-expanded', 'false');
  1480. toggle.setAttribute('aria-label', 'Ouvrir le menu');
  1481. }
  1482. });
  1483. })();
  1484. // Active section highlight in nav (subtle — color shift only)
  1485. (function () {
  1486. const sections = document.querySelectorAll('main section[id]');
  1487. const navLinks = document.querySelectorAll('.nav-links a[href^="#"]');
  1488. if (!('IntersectionObserver' in window) || !sections.length) return;
  1489. const map = new Map();
  1490. navLinks.forEach(a => {
  1491. const id = a.getAttribute('href').slice(1);
  1492. map.set(id, a);
  1493. });
  1494. const io = new IntersectionObserver((entries) => {
  1495. entries.forEach(entry => {
  1496. const link = map.get(entry.target.id);
  1497. if (!link) return;
  1498. if (entry.isIntersecting) {
  1499. navLinks.forEach(a => a.style.color = '');
  1500. link.style.color = 'var(--g100)';
  1501. }
  1502. });
  1503. }, { rootMargin: '-40% 0px -55% 0px', threshold: 0 });
  1504. sections.forEach(s => io.observe(s));
  1505. })();
  1506. </script>
  1507. </body>
  1508. </html>