index.html 55 KB

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