templates/application/whileresume/website/candidates/homepage.html.twig line 1

Open in your IDE?
  1. {% extends 'application/whileresume/website/layout-social.html.twig' %}
  2. {% set isFR = app.request.locale == 'fr' %}
  3. {% set _keys = [
  4. 'hero_eyebrow','hero_title_pre','hero_title_accent','hero_title_post','hero_title_accent2','hero_title_2',
  5. 'hero_lede_pre','hero_lede_brand','hero_lede_mid','hero_lede_word','hero_lede_post',
  6. 'hero_cta_signup','hero_cta_login',
  7. 'hero_search_placeholder','hero_popular_label','hero_btn_ios','hero_btn_android',
  8. 'hero_default_title','hero_search_button','hero_byline_jobs','hero_byline_apps','hero_byline_free','hero_kbd_enter',
  9. 'search_loading','search_no_results','search_no_results_hint','search_results_count','search_view_all','search_view_offer','search_clear',
  10. 'how_eyebrow','how_title','how_lede',
  11. 'how1_title','how1_desc','how2_title','how2_desc','how3_title','how3_desc',
  12. 'feat1_label','feat1_title','feat1_p1','feat1_p2','feat1_quote','feat1_author','feat1_role',
  13. 'feat2_label','feat2_title','feat2_p1','feat2_p2','feat2_quote','feat2_author','feat2_role',
  14. 'feat3_label','feat3_title','feat3_p1','feat3_p2','feat3_quote','feat3_author','feat3_role',
  15. 'feat4_label','feat4_title','feat4_p1','feat4_p2','feat4_quote','feat4_author','feat4_role',
  16. 'signup_eyebrow','signup_title','signup_lede','signup_email_ph','signup_pass_ph','signup_pass2_ph',
  17. 'signup_terms_pre','signup_terms_link','signup_btn','signup_login_pre','signup_login_link',
  18. 'signup_perk1','signup_perk2','signup_perk3',
  19. 'apps_eyebrow','apps_title','apps_lede','apps_ios','apps_android','apps_web','apps_ios_desc','apps_android_desc','apps_web_desc',
  20. 'articles_title','articles_view_all','read_article',
  21. 'final_eyebrow','final_title',
  22. 'final_recruiter_label','final_recruiter_title','final_recruiter_desc',
  23. 'final_candidate_label','final_candidate_title','final_candidate_desc',
  24. 'final_candidate','final_recruiter'
  25. ] %}
  26. {% set t = {} %}
  27. {% for k in _keys %}
  28. {% set t = t|merge({(k): ('homepage.' ~ k)|trans({}, 'whr-public')}) %}
  29. {% endfor %}
  30. {% block title %}{{ page.shortTitle }}{% endblock %}
  31. {% block description %}{{ page.shortDescription }}{% endblock %}
  32. {% block robots %}{{ page.robots }}{% endblock %}
  33. {% block canonical %}{% include "/vitrine/lexend/components/languages/canonical_classic.html.twig" %}{% endblock %}
  34. {% block css %}
  35. {{ parent() }}
  36. <style>
  37. :root{
  38. --wr-bg:#FBFCFE;
  39. --wr-bg-2:#F4F6FB;
  40. --wr-card:#FFFFFF;
  41. --wr-violet:#8A63C1;
  42. --wr-violet-2:#A98AD3;
  43. --wr-violet-soft:#F2EDFA;
  44. --wr-violet-softer:#F8F4FD;
  45. --wr-violet-dark:#6B47A6;
  46. --wr-ink:#1E1B2E;
  47. --wr-ink-2:#374151;
  48. --wr-muted:#6B7280;
  49. --wr-muted-2:#9CA3AF;
  50. --wr-line:#EEF1F7;
  51. --wr-line-2:#E5E9F0;
  52. --wr-shadow:0 1px 2px rgba(30,27,46,.04),0 4px 16px rgba(30,27,46,.04);
  53. --wr-shadow-hover:0 4px 8px rgba(138,99,192,.08),0 12px 32px rgba(138,99,192,.1);
  54. /* Accents colorés pour les logos d'offres (lettres) */
  55. --wr-acc-yellow:#FEF3C7; --wr-acc-yellow-fg:#B45309;
  56. --wr-acc-green:#D1FAE5; --wr-acc-green-fg:#047857;
  57. --wr-acc-pink:#FCE7F3; --wr-acc-pink-fg:#BE185D;
  58. --wr-acc-blue:#DBEAFE; --wr-acc-blue-fg:#1E40AF;
  59. --wr-acc-orange:#FED7AA; --wr-acc-orange-fg:#C2410C;
  60. --wr-acc-violet:#EDE9FE; --wr-acc-violet-fg:#6D28D9;
  61. --wr-acc-cyan:#CFFAFE; --wr-acc-cyan-fg:#0E7490;
  62. }
  63. /* ═══════════════════════════════════════════════════════════════════
  64. PLEINE LARGEUR — On retire la réservation d'espace de la sidebar droite
  65. ═══════════════════════════════════════════════════════════════════ */
  66. body .main-content.right-chat-active{padding-right:0!important}
  67. body .main-content{padding-right:0!important}
  68. body .right-chat{display:none!important}
  69. body .middle-sidebar-bottom .middle-sidebar-left{padding-right:0!important;max-width:none!important;width:100%!important}
  70. body .middle-sidebar-bottom{max-width:none!important}
  71. .wr{margin:-15px -15px 0;background:var(--wr-bg);color:var(--wr-ink);font-family:inherit;font-size:15px;line-height:1.6;-webkit-font-smoothing:antialiased}
  72. @media(max-width:991px){.wr{margin:0 -15px}}
  73. .wr *{box-sizing:border-box}
  74. .wr a{color:inherit;text-decoration:none}
  75. /* ═══════════════════════════════════════════════════════════════════
  76. SECTIONS GENERIC — Fond UNIFIÉ partout (pas d'alternance)
  77. ═══════════════════════════════════════════════════════════════════ */
  78. .wr-section{padding:80px 32px;background:var(--wr-bg);position:relative}
  79. .wr-section--tight{padding:48px 32px}
  80. @media(max-width:768px){.wr-section{padding:56px 20px}.wr-section--tight{padding:36px 20px}}
  81. /* Filet décoratif au lieu d'un changement de couleur */
  82. .wr-section + .wr-section::before{
  83. content:"";
  84. position:absolute;top:0;left:50%;transform:translateX(-50%);
  85. width:80px;height:1px;
  86. background:linear-gradient(90deg,transparent,var(--wr-line-2),transparent);
  87. }
  88. .wr-container{max-width:1200px;margin:0 auto;position:relative}
  89. /* ═══ Eyebrow ═══ */
  90. .wr-eyebrow{
  91. display:inline-flex;align-items:center;gap:8px;
  92. padding:6px 14px;border-radius:100px;
  93. background:var(--wr-violet-soft);
  94. color:var(--wr-violet-dark);
  95. font-size:11.5px;font-weight:600;
  96. text-transform:uppercase;letter-spacing:.12em;
  97. margin-bottom:22px;
  98. }
  99. .wr-eyebrow-dot{width:6px;height:6px;border-radius:50%;background:var(--wr-violet);animation:wrPulse 2.4s ease-in-out infinite}
  100. @keyframes wrPulse{0%,100%{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}
  101. /* ═══ Titres ═══ */
  102. .wr-title{
  103. font-family:inherit;
  104. font-weight:700;
  105. font-size:28px;line-height:1.15;letter-spacing:-0.025em;
  106. color:var(--wr-ink);
  107. margin:0 auto 16px;
  108. max-width:1200px;
  109. }
  110. @media(min-width:768px){.wr-title{font-size:34px}}
  111. @media(min-width:1024px){.wr-title{font-size:40px}}
  112. .wr-title--sm{font-size:24px}
  113. @media(min-width:768px){.wr-title--sm{font-size:30px}}
  114. .wr-title em{font-style:normal;font-weight:700;color:var(--wr-violet)}
  115. .wr-lede{
  116. font-size:17px;line-height:1.55;font-weight:400;
  117. color:var(--wr-ink-2);
  118. margin:0 auto;max-width:680px;
  119. }
  120. .wr-section-head{text-align:center;margin-bottom:56px}
  121. /* ═══════════════════════════════════════════════════════════════════
  122. HERO — Style soft, recherche dashboard, boutons pleins
  123. ═══════════════════════════════════════════════════════════════════ */
  124. @keyframes wrFadeUp{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}
  125. @keyframes wrPulse2{0%{box-shadow:0 0 0 0 rgba(16,185,129,.4)}70%{box-shadow:0 0 0 8px rgba(16,185,129,0)}100%{box-shadow:0 0 0 0 rgba(16,185,129,0)}}
  126. /* ═══ Reveal au scroll (Intersection Observer ajoute .is-revealed) ═══ */
  127. .reveal{opacity:0;transform:translateY(24px);transition:opacity .8s cubic-bezier(.2,.7,.2,1),transform .8s cubic-bezier(.2,.7,.2,1)}
  128. .reveal.is-revealed{opacity:1;transform:translateY(0)}
  129. .reveal--left{transform:translateX(-32px) translateY(0)}
  130. .reveal--left.is-revealed{transform:translateX(0)}
  131. .reveal--right{transform:translateX(32px) translateY(0)}
  132. .reveal--right.is-revealed{transform:translateX(0)}
  133. .reveal--scale{transform:scale(.96);opacity:0}
  134. .reveal--scale.is-revealed{transform:scale(1);opacity:1}
  135. .reveal[data-reveal-delay="1"]{transition-delay:.08s}
  136. .reveal[data-reveal-delay="2"]{transition-delay:.16s}
  137. .reveal[data-reveal-delay="3"]{transition-delay:.24s}
  138. .reveal[data-reveal-delay="4"]{transition-delay:.32s}
  139. @media(prefers-reduced-motion:reduce){.reveal{opacity:1!important;transform:none!important;transition:none!important}}
  140. .hero{
  141. position:relative;
  142. background:var(--wr-bg);
  143. padding:24px 32px 0;
  144. overflow:hidden;
  145. }
  146. @media(max-width:768px){.hero{padding:18px 18px 0}}
  147. /* Décor : 2 blobs très flous violet pâle */
  148. .hero::before{
  149. content:"";position:absolute;
  150. top:-260px;right:-180px;width:560px;height:560px;
  151. background:radial-gradient(circle,rgba(138,99,192,.14) 0%,transparent 65%);
  152. pointer-events:none;filter:blur(50px);
  153. }
  154. .hero::after{
  155. content:"";position:absolute;
  156. top:120px;left:-180px;width:480px;height:480px;
  157. background:radial-gradient(circle,rgba(138,99,192,.09) 0%,transparent 65%);
  158. pointer-events:none;filter:blur(50px);
  159. }
  160. .hero-inner{position:relative;z-index:2;max-width:1200px;margin:0 auto;text-align:center}
  161. /* ═══ Eyebrow ═══ */
  162. .hero-badge{
  163. display:inline-flex;align-items:center;gap:8px;
  164. padding:7px 16px;border-radius:100px;
  165. background:var(--wr-violet-soft);
  166. color:var(--wr-violet-dark);
  167. font-size:12px;font-weight:600;
  168. text-transform:uppercase;letter-spacing:.1em;
  169. margin-bottom:10px;
  170. opacity:0;transform:translateY(8px);
  171. animation:wrFadeUp .8s ease forwards;
  172. }
  173. .hero-badge-dot{width:6px;height:6px;border-radius:50%;background:var(--wr-violet);animation:wrPulse2 2s ease infinite}
  174. /* ═══ Titre — 57px desktop, plein largeur conteneur ═══ */
  175. .hero-title{
  176. font-weight:700;
  177. font-size:24px;line-height:1.05;letter-spacing:-0.04em;
  178. color:var(--wr-ink);
  179. margin:0 auto 12px;
  180. width:100%;max-width:1200px;
  181. opacity:0;transform:translateY(12px);
  182. animation:wrFadeUp .9s cubic-bezier(.2,.7,.2,1) .15s forwards;
  183. }
  184. @media(min-width:768px){.hero-title{font-size:40px;letter-spacing:-0.045em}}
  185. @media(min-width:1100px){.hero-title{font-size:57px;letter-spacing:-0.045em}}
  186. .hero-title-accent{
  187. color:var(--wr-violet);
  188. }
  189. .hero-lede{
  190. font-size:15px;line-height:1.5;color:var(--wr-ink-2);font-weight:400;
  191. margin:0 auto 16px;max-width:680px;
  192. opacity:0;animation:wrFadeUp .9s ease .4s forwards;
  193. }
  194. @media(min-width:768px){.hero-lede{font-size:17px}}
  195. .hero-lede-accent{color:var(--wr-violet);font-weight:600}
  196. /* ═══ Recherche — pleine largeur (alignée sur la liste 1200px) ═══ */
  197. .hero-search-wrap{
  198. max-width:1200px;margin:0 auto 12px;
  199. opacity:0;animation:wrFadeUp .9s ease .55s forwards;
  200. position:relative;z-index:5;
  201. }
  202. .hero-search{
  203. background:var(--wr-card);
  204. border-radius:14px;
  205. box-shadow:0 0 20px 0 rgba(0,0,0,0.05),0 16px 40px rgba(138,99,192,.06);
  206. padding:10px;
  207. position:relative;
  208. }
  209. .hero-search-inner{
  210. display:flex;align-items:center;gap:10px;
  211. padding:10px 14px;border-radius:10px;
  212. background:#F9FAFB;border:1px solid #E5E7EB;
  213. transition:border-color .2s,background .2s;
  214. }
  215. .hero-search-inner:focus-within{
  216. border-color:rgba(138,99,192,.4);
  217. background:#fff;
  218. }
  219. .hero-search-icon{color:var(--wr-muted-2);display:flex;flex-shrink:0}
  220. .hero-search-icon svg{width:16px;height:16px}
  221. .hero-search-input{
  222. flex:1;border:0;outline:0;background:transparent;
  223. font-size:14.5px;font-family:inherit;color:var(--wr-ink);
  224. padding:6px 0;min-width:0;
  225. }
  226. .hero-search-input::placeholder{color:var(--wr-muted-2)}
  227. .hero-search-clear{
  228. background:none;border:0;color:var(--wr-muted-2);cursor:pointer;
  229. padding:4px;display:none;font-family:inherit;
  230. border-radius:6px;transition:background .15s,color .15s;
  231. }
  232. .hero-search-clear:hover{background:var(--wr-violet-soft);color:var(--wr-violet)}
  233. .hero-search-clear.is-visible{display:flex;align-items:center}
  234. .hero-search-clear svg{width:14px;height:14px}
  235. .hero-search-kbd{
  236. display:none;align-items:center;
  237. padding:3px 8px;background:#fff;border:1px solid #E5E7EB;border-radius:6px;
  238. font-size:10.5px;font-weight:600;color:var(--wr-muted);
  239. font-family:inherit;letter-spacing:.02em;white-space:nowrap;flex-shrink:0;
  240. }
  241. .hero-search-inner:focus-within .hero-search-kbd{display:inline-flex}
  242. /* ═══ États de la liste de jobs (header, empty, loading) ═══ */
  243. .hero-jobs-header{
  244. display:flex;align-items:center;justify-content:space-between;gap:10px;
  245. padding:14px 22px 10px;
  246. border-bottom:1px solid var(--wr-line);
  247. margin-bottom:4px;
  248. }
  249. @media(max-width:540px){.hero-jobs-header{padding:12px 16px 8px}}
  250. .hero-jobs-count{
  251. font-size:11.5px;color:var(--wr-muted);
  252. text-transform:uppercase;letter-spacing:.08em;font-weight:600;
  253. }
  254. .hero-jobs-count strong{color:var(--wr-violet);font-weight:800;font-size:13px;margin-right:4px}
  255. .hero-jobs-link{
  256. font-size:11px;font-weight:700;
  257. color:var(--wr-violet);
  258. text-transform:uppercase;letter-spacing:.08em;
  259. text-decoration:none;
  260. display:inline-flex;align-items:center;gap:5px;
  261. transition:color .15s,transform .15s;
  262. }
  263. .hero-jobs-link:hover{color:var(--wr-violet-dark);text-decoration:none;transform:translateX(2px)}
  264. .hero-jobs-link svg{width:11px;height:11px}
  265. .hero-jobs-empty{text-align:center;padding:48px 20px;color:var(--wr-muted)}
  266. .hero-jobs-empty-icon{width:48px;height:48px;border-radius:14px;background:var(--wr-violet-soft);color:var(--wr-violet);display:inline-flex;align-items:center;justify-content:center;margin-bottom:14px}
  267. .hero-jobs-empty-icon svg{width:22px;height:22px}
  268. .hero-jobs-empty-title{font-weight:600;font-size:14px;color:var(--wr-ink);margin:0 0 4px}
  269. .hero-jobs-empty-hint{font-size:13px;margin:0;color:var(--wr-muted)}
  270. .hero-jobs-loading{text-align:center;padding:36px 20px;color:var(--wr-muted);font-size:13px;display:flex;align-items:center;justify-content:center;gap:10px}
  271. .hero-jobs-spinner{width:16px;height:16px;border-radius:50%;border:2px solid var(--wr-violet-soft);border-top-color:var(--wr-violet);animation:wrSpin .7s linear infinite}
  272. @keyframes wrSpin{to{transform:rotate(360deg)}}
  273. /* ═══ Pills "Populaire" sous la recherche ═══ */
  274. .hero-popular{
  275. display:flex;align-items:center;justify-content:center;gap:6px;flex-wrap:wrap;
  276. margin-bottom:18px;
  277. opacity:0;animation:wrFadeUp .9s ease .7s forwards;
  278. }
  279. .hero-popular-label{
  280. font-size:11px;font-weight:600;color:var(--wr-muted);
  281. text-transform:uppercase;letter-spacing:.06em;
  282. margin-right:4px;
  283. }
  284. .hero-popular-pill{
  285. display:inline-flex;align-items:center;gap:5px;
  286. padding:6px 12px;border-radius:100px;
  287. background:var(--wr-violet-soft);
  288. color:var(--wr-violet);
  289. font-size:12.5px;font-weight:500;font-family:inherit;
  290. text-decoration:none;cursor:pointer;
  291. border:1px solid transparent;
  292. transition:background .15s,border-color .15s,transform .15s,color .15s;
  293. }
  294. .hero-popular-pill:hover{
  295. background:#EDE9FE;
  296. border-color:rgba(138,99,192,.2);
  297. transform:translateY(-1px);
  298. color:var(--wr-violet);
  299. text-decoration:none;
  300. }
  301. .hero-popular-pill.is-active{
  302. background:var(--wr-violet);color:#fff;border-color:var(--wr-violet);
  303. }
  304. .hero-popular-pill.is-active:hover{background:var(--wr-violet-dark);color:#fff}
  305. .hero-popular-pill-icon{font-size:13px;line-height:1}
  306. /* ═══ CTA hero (boutons inscription + connexion pour anonymes) ═══ */
  307. .hero-cta{
  308. display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap;
  309. margin:24px 0 8px;
  310. opacity:0;animation:wrFadeUp .9s ease 1.1s forwards;
  311. }
  312. .hero-cta-btn,
  313. .hero-cta-btn:link,
  314. .hero-cta-btn:visited,
  315. .hero-cta-btn:hover,
  316. .hero-cta-btn:focus,
  317. .hero-cta-btn:active{
  318. color:#fff !important;
  319. text-decoration:none !important;
  320. }
  321. .hero-cta-btn{
  322. display:inline-flex;align-items:center;gap:8px;
  323. padding:11px 20px;border-radius:11px;
  324. font-size:13.5px;font-weight:700;font-family:inherit;
  325. line-height:1;
  326. background:var(--wr-violet);border:1px solid var(--wr-violet);
  327. box-shadow:0 4px 14px rgba(138,99,193,.32);
  328. transition:background .15s,border-color .15s,transform .15s,box-shadow .15s;
  329. }
  330. .hero-cta-btn:hover{
  331. background:var(--wr-violet-dark);border-color:var(--wr-violet-dark);
  332. transform:translateY(-2px);
  333. box-shadow:0 6px 20px rgba(138,99,193,.4);
  334. }
  335. .hero-cta-btn svg{width:15px;height:15px;flex-shrink:0;stroke:#fff !important;color:#fff !important}
  336. .hero-cta-btn span{color:#fff !important}
  337. @media(max-width:540px){.hero-cta{flex-direction:column;align-items:stretch}.hero-cta-btn{justify-content:center}}
  338. /* ═══ Boutons stores — VIOLET PLEIN BLANC ═══ */
  339. .hero-stores{
  340. display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap;
  341. margin-bottom:48px;
  342. opacity:0;animation:wrFadeUp .9s ease .85s forwards;
  343. }
  344. .hero-store-btn{
  345. display:inline-flex;align-items:center;gap:10px;
  346. padding:13px 24px;border-radius:12px;
  347. background:var(--wr-violet);
  348. border:0;
  349. color:#fff;
  350. font-size:14px;font-weight:600;
  351. text-decoration:none;
  352. transition:background .15s,transform .15s,box-shadow .15s;
  353. box-shadow:0 4px 12px rgba(138,99,192,.3);
  354. }
  355. .hero-store-btn:hover{
  356. background:var(--wr-violet-dark);
  357. color:#fff;
  358. transform:translateY(-2px);
  359. box-shadow:0 8px 22px rgba(138,99,192,.4);
  360. text-decoration:none;
  361. }
  362. .hero-store-btn-icon{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px}
  363. .hero-store-btn-icon svg{width:18px;height:18px}
  364. @media(max-width:540px){.hero-stores{flex-direction:column;align-items:stretch;gap:10px}.hero-store-btn{justify-content:center}}
  365. /* ═══════════════════════════════════════════════════════════════════
  366. LISTE PAR DÉFAUT SOUS LE HERO (offres récentes)
  367. ═══════════════════════════════════════════════════════════════════ */
  368. .hero-default-jobs{
  369. position:relative;z-index:2;
  370. max-width:1200px;margin:0 auto;
  371. background:var(--wr-card);
  372. border:1px solid var(--wr-line);
  373. border-radius:18px;
  374. padding:8px 0;
  375. box-shadow:var(--wr-shadow);
  376. opacity:0;animation:wrFadeUp .9s ease 1s forwards;
  377. text-align:left;
  378. }
  379. .hero-default-job{
  380. display:flex;align-items:center;gap:16px;
  381. padding:14px 22px;
  382. text-decoration:none;color:inherit;
  383. border-bottom:1px solid var(--wr-line);
  384. transition:background .15s;
  385. }
  386. .hero-default-job:last-child{border-bottom:0}
  387. .hero-default-job:hover{background:var(--wr-violet-softer);text-decoration:none;color:inherit}
  388. .hero-default-job-logo{
  389. width:42px;height:42px;border-radius:11px;flex-shrink:0;
  390. display:flex;align-items:center;justify-content:center;
  391. font-weight:700;font-size:16px;overflow:hidden;
  392. }
  393. .hero-default-job-logo img{width:100%;height:100%;object-fit:cover}
  394. /* 7 variantes de couleurs cyclées par index */
  395. .hero-default-job:nth-child(7n+1) .hero-default-job-logo{background:var(--wr-acc-yellow);color:var(--wr-acc-yellow-fg)}
  396. .hero-default-job:nth-child(7n+2) .hero-default-job-logo{background:var(--wr-acc-green);color:var(--wr-acc-green-fg)}
  397. .hero-default-job:nth-child(7n+3) .hero-default-job-logo{background:var(--wr-acc-pink);color:var(--wr-acc-pink-fg)}
  398. .hero-default-job:nth-child(7n+4) .hero-default-job-logo{background:var(--wr-acc-blue);color:var(--wr-acc-blue-fg)}
  399. .hero-default-job:nth-child(7n+5) .hero-default-job-logo{background:var(--wr-acc-orange);color:var(--wr-acc-orange-fg)}
  400. .hero-default-job:nth-child(7n+6) .hero-default-job-logo{background:var(--wr-acc-violet);color:var(--wr-acc-violet-fg)}
  401. .hero-default-job:nth-child(7n+7) .hero-default-job-logo{background:var(--wr-acc-cyan);color:var(--wr-acc-cyan-fg)}
  402. .hero-default-job-info{flex:1;min-width:0}
  403. .hero-default-job-title{
  404. font-weight:600;font-size:14.5px;color:var(--wr-ink);
  405. margin:0 0 2px;line-height:1.3;
  406. white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  407. }
  408. .hero-default-job-meta{
  409. font-size:12.5px;color:var(--wr-muted);margin:0;
  410. white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  411. display:flex;align-items:center;gap:8px;
  412. }
  413. .hero-default-job-meta-sep{display:inline-block;width:3px;height:3px;border-radius:50%;background:var(--wr-muted-2);flex-shrink:0}
  414. .hero-default-job-arrow{flex-shrink:0;color:var(--wr-muted-2);transition:color .15s,transform .15s}
  415. .hero-default-job-arrow svg{width:15px;height:15px}
  416. .hero-default-job:hover .hero-default-job-arrow{color:var(--wr-violet);transform:translateX(3px)}
  417. @media(max-width:768px){
  418. .hero-default-jobs{margin:0 -18px;border-radius:14px}
  419. .hero-default-job{padding:12px 16px;gap:12px}
  420. .hero-default-job-logo{width:36px;height:36px;font-size:13px}
  421. .hero-default-job-title{font-size:13.5px}
  422. .hero-default-job-meta{font-size:11.5px;gap:6px;flex-wrap:wrap;white-space:normal}
  423. }
  424. /* ═══════════════════════════════════════════════════════════════════
  425. SECTION : 3 PARCOURS
  426. ═══════════════════════════════════════════════════════════════════ */
  427. .paths-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
  428. @media(max-width:991px){.paths-grid{grid-template-columns:1fr;gap:14px}}
  429. .path-card{
  430. position:relative;
  431. background:var(--wr-card);
  432. border:1px solid var(--wr-line);
  433. border-radius:20px;padding:28px;
  434. display:flex;flex-direction:column;
  435. transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease;
  436. box-shadow:var(--wr-shadow);
  437. }
  438. .path-card:hover{transform:translateY(-4px);box-shadow:var(--wr-shadow-hover);border-color:var(--wr-violet-2)}
  439. .path-card-illu{
  440. width:64px;height:64px;border-radius:16px;
  441. background:var(--wr-violet-soft);color:var(--wr-violet);
  442. display:flex;align-items:center;justify-content:center;
  443. margin-bottom:22px;
  444. }
  445. .path-card-illu svg{width:30px;height:30px}
  446. .path-card-label{
  447. display:inline-block;
  448. font-size:11px;font-weight:600;
  449. color:var(--wr-violet-dark);text-transform:uppercase;letter-spacing:.1em;
  450. margin-bottom:10px;align-self:flex-start;
  451. }
  452. .path-card-title{
  453. font-weight:500;font-size:22px;line-height:1.25;letter-spacing:-0.015em;
  454. color:var(--wr-ink);margin:0 0 10px;
  455. }
  456. .path-card-desc{
  457. font-size:14px;line-height:1.6;color:var(--wr-muted);
  458. margin:0 0 22px;flex:1;
  459. }
  460. .path-card-cta{
  461. display:inline-flex;align-items:center;justify-content:center;gap:6px;
  462. background:var(--wr-violet);color:#fff;
  463. padding:12px 18px;border-radius:11px;
  464. font-size:13px;font-weight:600;
  465. align-self:stretch;
  466. transition:background .15s,transform .15s,box-shadow .15s;
  467. box-shadow:0 2px 8px rgba(138,99,192,.2);
  468. }
  469. .path-card-cta:hover{background:var(--wr-violet-dark);color:#fff;text-decoration:none;transform:translateY(-1px);box-shadow:0 4px 12px rgba(138,99,192,.3)}
  470. .path-card-cta svg{width:13px;height:13px;transition:transform .15s}
  471. .path-card-cta:hover svg{transform:translateX(3px)}
  472. /* ═══════════════════════════════════════════════════════════════════
  473. COMMENT ÇA MARCHE — Card crème englobante avec 3 sous-cards
  474. ═══════════════════════════════════════════════════════════════════ */
  475. .how-card{
  476. background:#F4ECE1;
  477. border-radius:24px;
  478. padding:32px 24px;
  479. display:grid;grid-template-columns:repeat(3,1fr);gap:24px;
  480. position:relative;
  481. }
  482. @media(max-width:991px){.how-card{grid-template-columns:1fr;gap:8px;padding:24px 16px}}
  483. @media(min-width:992px){
  484. /* Séparateurs verticaux entre les 3 cellules */
  485. .how-card .how-step + .how-step{border-left:1px solid rgba(28,25,22,.08)}
  486. }
  487. .how-step{
  488. display:flex;flex-direction:column;align-items:center;text-align:center;
  489. padding:16px 20px;
  490. gap:16px;
  491. }
  492. .how-step-illu{
  493. width:100%;max-width:280px;aspect-ratio:1/1;
  494. border-radius:16px;
  495. background:rgba(255,255,255,.5);
  496. display:flex;align-items:center;justify-content:center;
  497. margin-bottom:4px;
  498. overflow:hidden;
  499. }
  500. .how-step-illu img{width:100%;height:100%;object-fit:contain;display:block}
  501. .how-step-illu svg{width:55%;height:55%;opacity:.85}
  502. .how-step-title{
  503. font-weight:700;font-size:18px;line-height:1.3;letter-spacing:-0.01em;
  504. color:var(--wr-ink);margin:0;
  505. }
  506. @media(min-width:992px){.how-step-title{font-size:20px}}
  507. .how-step-desc{
  508. font-size:14px;line-height:1.55;color:var(--wr-ink-2);
  509. margin:0;max-width:320px;
  510. }
  511. /* ═══════════════════════════════════════════════════════════════════
  512. FEATURES 01-04 — Splits alternés image/texte avec témoignages
  513. ═══════════════════════════════════════════════════════════════════ */
  514. .feat-block{
  515. display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:center;
  516. margin-bottom:64px;
  517. }
  518. .feat-block:last-child{margin-bottom:0}
  519. @media(max-width:991px){
  520. .feat-block{grid-template-columns:1fr;gap:24px;margin-bottom:48px}
  521. }
  522. /* Alterner : 01 illu droite, 02 illu gauche, 03 illu droite, 04 illu gauche */
  523. .feat-block:nth-child(odd) .feat-illu{order:2}
  524. .feat-block:nth-child(odd) .feat-content{order:1}
  525. .feat-block:nth-child(even) .feat-illu{order:1}
  526. .feat-block:nth-child(even) .feat-content{order:2}
  527. @media(max-width:991px){
  528. .feat-block .feat-illu{order:1}
  529. .feat-block .feat-content{order:2}
  530. }
  531. .feat-illu{
  532. background:#F5EDE3;
  533. border-radius:20px;
  534. aspect-ratio:1/1;
  535. display:flex;align-items:center;justify-content:center;
  536. color:var(--wr-violet);
  537. overflow:hidden;
  538. position:relative;
  539. }
  540. .feat-illu img{width:100%;height:100%;object-fit:contain;display:block}
  541. .feat-illu svg{width:50%;height:50%;opacity:.85}
  542. .feat-content{display:flex;flex-direction:column;gap:18px}
  543. .feat-label{
  544. font-size:30px;font-weight:800;
  545. color:var(--wr-ink);
  546. letter-spacing:-0.02em;
  547. margin:0;line-height:1;
  548. }
  549. .feat-title{
  550. font-weight:700;font-size:24px;line-height:1.2;letter-spacing:-0.02em;
  551. color:var(--wr-ink);margin:0;
  552. }
  553. @media(min-width:768px){.feat-title{font-size:28px}}
  554. @media(min-width:1100px){.feat-title{font-size:30px}}
  555. .feat-desc{
  556. display:flex;flex-direction:column;gap:14px;
  557. }
  558. .feat-desc p{
  559. font-size:15px;line-height:1.6;color:var(--wr-ink-2);
  560. margin:0;opacity:.85;
  561. }
  562. @media(min-width:1100px){.feat-desc p{font-size:16px}}
  563. .feat-desc strong{color:var(--wr-ink);font-weight:700;opacity:1}
  564. .feat-quote{
  565. background:var(--wr-card);
  566. border:1px solid var(--wr-line);
  567. border-radius:14px;
  568. padding:18px 20px;
  569. display:flex;flex-direction:column;gap:10px;
  570. margin-top:8px;
  571. }
  572. .feat-quote-text{
  573. font-size:14px;line-height:1.55;color:var(--wr-ink-2);
  574. margin:0;font-style:italic;
  575. }
  576. .feat-quote-author{
  577. display:flex;flex-direction:column;
  578. }
  579. .feat-quote-name{font-size:13px;font-weight:700;color:var(--wr-ink);margin:0}
  580. .feat-quote-role{font-size:12px;color:var(--wr-muted);margin:0}
  581. /* ═══════════════════════════════════════════════════════════════════
  582. MATCH
  583. ═══════════════════════════════════════════════════════════════════ */
  584. .match-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:60px;align-items:center}
  585. @media(max-width:991px){.match-grid{grid-template-columns:1fr;gap:40px}}
  586. .match-text .wr-title{margin-left:0;text-align:left}
  587. .match-text .wr-lede{margin-left:0;text-align:left}
  588. .match-text .wr-eyebrow{margin-bottom:20px}
  589. .match-features{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:32px}
  590. @media(max-width:540px){.match-features{grid-template-columns:1fr}}
  591. .match-feature{
  592. background:var(--wr-card);border:1px solid var(--wr-line);
  593. border-radius:14px;padding:18px;
  594. transition:transform .15s,border-color .15s,box-shadow .15s;
  595. }
  596. .match-feature:hover{transform:translateY(-2px);border-color:var(--wr-violet-soft);box-shadow:var(--wr-shadow)}
  597. .match-feature-icon{
  598. width:34px;height:34px;border-radius:10px;
  599. background:var(--wr-violet-soft);color:var(--wr-violet);
  600. display:inline-flex;align-items:center;justify-content:center;margin-bottom:12px;
  601. }
  602. .match-feature-icon svg{width:16px;height:16px}
  603. .match-feature-title{font-weight:600;font-size:14px;line-height:1.3;color:var(--wr-ink);margin:0 0 5px}
  604. .match-feature-desc{font-size:12.5px;line-height:1.5;color:var(--wr-muted);margin:0}
  605. .match-visual{position:relative;display:flex;justify-content:center;align-items:center;padding:40px 0}
  606. .match-stack{position:relative;width:100%;max-width:340px;height:340px}
  607. .match-stack-card{
  608. position:absolute;
  609. background:var(--wr-card);border:1px solid var(--wr-line);
  610. border-radius:16px;padding:14px;
  611. display:flex;align-items:center;gap:12px;
  612. box-shadow:var(--wr-shadow);width:100%;
  613. transition:transform .3s ease,box-shadow .3s ease;
  614. cursor:pointer;
  615. }
  616. .match-stack-card:hover{
  617. transform:translateY(-4px) rotate(0deg)!important;
  618. box-shadow:0 20px 50px rgba(138,99,192,.22)!important;
  619. z-index:10!important;
  620. }
  621. .match-stack-card:nth-child(1){top:0;transform:rotate(-6deg) translateX(-10px);z-index:1;animation:wrFloat1 6s ease-in-out infinite}
  622. .match-stack-card:nth-child(2){top:78px;left:14px;transform:rotate(2deg);z-index:3;box-shadow:0 16px 40px rgba(138,99,192,.18);animation:wrFloat2 6s ease-in-out -2s infinite}
  623. .match-stack-card:nth-child(3){top:156px;transform:rotate(-3deg) translateX(8px);z-index:2;animation:wrFloat3 6s ease-in-out -4s infinite}
  624. .match-stack-card:nth-child(4){top:234px;left:20px;transform:rotate(4deg);z-index:1;animation:wrFloat4 6s ease-in-out -1s infinite}
  625. @keyframes wrFloat1{0%,100%{transform:rotate(-6deg) translate(-10px,0)}50%{transform:rotate(-6deg) translate(-10px,-8px)}}
  626. @keyframes wrFloat2{0%,100%{transform:rotate(2deg) translate(0,0)}50%{transform:rotate(2deg) translate(0,-6px)}}
  627. @keyframes wrFloat3{0%,100%{transform:rotate(-3deg) translate(8px,0)}50%{transform:rotate(-3deg) translate(8px,-7px)}}
  628. @keyframes wrFloat4{0%,100%{transform:rotate(4deg) translate(0,0)}50%{transform:rotate(4deg) translate(0,-5px)}}
  629. .match-stack-logo{
  630. width:38px;height:38px;border-radius:10px;
  631. background:var(--wr-violet-soft);color:var(--wr-violet);
  632. display:flex;align-items:center;justify-content:center;
  633. font-weight:700;font-size:14px;flex-shrink:0;
  634. }
  635. .match-stack-info{flex:1;min-width:0}
  636. .match-stack-title{font-weight:600;font-size:13px;color:var(--wr-ink);margin:0 0 2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3}
  637. .match-stack-meta{font-size:11px;color:var(--wr-muted);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  638. .match-stack-heart{
  639. width:28px;height:28px;border-radius:50%;
  640. background:#FEE2E2;color:#EF4444;
  641. display:flex;align-items:center;justify-content:center;flex-shrink:0;
  642. animation:wrHeartbeat 1.6s ease-in-out infinite;
  643. }
  644. .match-stack-card:nth-child(1) .match-stack-heart{animation-delay:0s}
  645. .match-stack-card:nth-child(2) .match-stack-heart{animation-delay:.4s}
  646. .match-stack-card:nth-child(3) .match-stack-heart{animation-delay:.8s}
  647. .match-stack-card:nth-child(4) .match-stack-heart{animation-delay:1.2s}
  648. .match-stack-heart svg{width:13px;height:13px;fill:currentColor}
  649. @keyframes wrHeartbeat{
  650. 0%,100%{transform:scale(1);box-shadow:0 0 0 0 rgba(239,68,68,.4)}
  651. 10%{transform:scale(1.18);box-shadow:0 0 0 0 rgba(239,68,68,.4)}
  652. 20%{transform:scale(1)}
  653. 30%{transform:scale(1.12)}
  654. 40%{transform:scale(1);box-shadow:0 0 0 10px rgba(239,68,68,0)}
  655. 100%{box-shadow:0 0 0 0 rgba(239,68,68,0)}
  656. }
  657. /* ═══════════════════════════════════════════════════════════════════
  658. SIGNUP FORM (entre feat 02 et 03)
  659. ═══════════════════════════════════════════════════════════════════ */
  660. .signup-card{
  661. position:relative;
  662. max-width:980px;margin:64px auto;
  663. background:linear-gradient(135deg, #FFFFFF 0%, #FAF7FF 100%);
  664. border:1px solid var(--wr-line);
  665. border-radius:32px;
  666. padding:48px 40px;
  667. box-shadow:0 4px 12px rgba(30,27,46,.04), 0 24px 64px rgba(138,99,192,.1);
  668. overflow:hidden;
  669. }
  670. @media(max-width:768px){.signup-card{padding:32px 22px;border-radius:24px;margin:48px auto}}
  671. /* Décor : 2 blobs violet pâle dans les coins */
  672. .signup-card::before{
  673. content:"";position:absolute;
  674. top:-120px;right:-120px;width:340px;height:340px;
  675. background:radial-gradient(circle,rgba(138,99,192,.12) 0%,transparent 65%);
  676. pointer-events:none;filter:blur(40px);
  677. }
  678. .signup-card::after{
  679. content:"";position:absolute;
  680. bottom:-100px;left:-80px;width:280px;height:280px;
  681. background:radial-gradient(circle,rgba(138,99,192,.08) 0%,transparent 65%);
  682. pointer-events:none;filter:blur(40px);
  683. }
  684. .signup-inner{position:relative;z-index:2;display:grid;grid-template-columns:1fr 1.2fr;gap:48px;align-items:center}
  685. @media(max-width:880px){.signup-inner{grid-template-columns:1fr;gap:28px}}
  686. .signup-text{display:flex;flex-direction:column;gap:14px}
  687. .signup-eyebrow{
  688. display:inline-flex;align-items:center;gap:8px;
  689. padding:7px 14px;border-radius:100px;
  690. background:var(--wr-violet-soft);color:var(--wr-violet-dark);
  691. font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  692. align-self:flex-start;
  693. }
  694. .signup-title{
  695. font-weight:700;font-size:28px;line-height:1.15;letter-spacing:-0.02em;
  696. color:var(--wr-ink);margin:0;
  697. }
  698. @media(min-width:768px){.signup-title{font-size:34px}}
  699. .signup-lede{font-size:15px;line-height:1.55;color:var(--wr-ink-2);margin:0;opacity:.85}
  700. .signup-perks{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
  701. .signup-perk{
  702. display:inline-flex;align-items:center;gap:6px;
  703. padding:6px 12px;border-radius:100px;
  704. background:var(--wr-card);border:1px solid var(--wr-line-2);
  705. font-size:12px;font-weight:600;color:var(--wr-ink-2);
  706. }
  707. .signup-perk svg{width:13px;height:13px;color:#10B981;stroke-width:3;flex-shrink:0}
  708. .signup-form{
  709. background:var(--wr-card);
  710. border:1px solid var(--wr-line);
  711. border-radius:20px;
  712. padding:24px;
  713. display:flex;flex-direction:column;gap:12px;
  714. box-shadow:0 1px 2px rgba(30,27,46,.03);
  715. }
  716. .signup-form-error{
  717. background:#FEF2F2;border:1px solid #FECACA;
  718. color:#991B1B;
  719. border-radius:12px;
  720. padding:10px 14px;
  721. font-size:13px;line-height:1.45;
  722. margin:0;
  723. }
  724. .signup-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  725. @media(max-width:540px){.signup-row{grid-template-columns:1fr}}
  726. .signup-field{display:flex;flex-direction:column;gap:0}
  727. .signup-card .signup-form input[type="email"],
  728. .signup-card .signup-form input[type="password"],
  729. .signup-card .signup-form input[type="text"]{
  730. width:100%;
  731. padding:13px 14px;
  732. border:1px solid var(--wr-line-2);border-radius:11px;
  733. background:#FAFBFD;
  734. font-size:14px;font-family:inherit;color:var(--wr-ink);
  735. outline:none;
  736. transition:border-color .15s,background .15s,box-shadow .15s;
  737. box-sizing:border-box;
  738. }
  739. .signup-card .signup-form input[type="email"]:focus,
  740. .signup-card .signup-form input[type="password"]:focus,
  741. .signup-card .signup-form input[type="text"]:focus{
  742. border-color:var(--wr-violet);background:#fff;
  743. box-shadow:0 0 0 3px rgba(138,99,192,.12);
  744. }
  745. .signup-card .signup-form input::placeholder{color:var(--wr-muted-2)}
  746. .signup-terms{
  747. display:flex;align-items:flex-start;gap:10px;
  748. font-size:12.5px;line-height:1.45;color:var(--wr-muted);
  749. margin:4px 0 0;
  750. }
  751. .signup-card .signup-form input[type="checkbox"]{
  752. width:16px;height:16px;flex-shrink:0;margin-top:2px;accent-color:var(--wr-violet);cursor:pointer;
  753. }
  754. .signup-terms a{color:var(--wr-violet);font-weight:600;text-decoration:underline}
  755. .signup-terms a:hover{color:var(--wr-violet-dark)}
  756. .signup-recaptcha{margin:4px 0 0}
  757. .signup-recaptcha > div{max-width:100%}
  758. .signup-submit{
  759. width:100%;
  760. padding:14px 22px;border-radius:12px;
  761. background:var(--wr-violet);color:#fff;border:0;
  762. font-size:14.5px;font-weight:700;font-family:inherit;
  763. cursor:pointer;
  764. display:inline-flex;align-items:center;justify-content:center;gap:8px;
  765. box-shadow:0 4px 14px rgba(138,99,192,.32);
  766. transition:background .15s,transform .15s,box-shadow .15s;
  767. margin-top:6px;
  768. }
  769. .signup-submit:hover{background:var(--wr-violet-dark);transform:translateY(-1px);box-shadow:0 6px 20px rgba(138,99,192,.4)}
  770. .signup-submit svg{width:14px;height:14px;transition:transform .15s}
  771. .signup-submit:hover svg{transform:translateX(3px)}
  772. .signup-login{
  773. text-align:center;font-size:13px;color:var(--wr-muted);margin:6px 0 0;
  774. }
  775. .signup-login a{color:var(--wr-violet);font-weight:600;text-decoration:none}
  776. .signup-login a:hover{color:var(--wr-violet-dark);text-decoration:underline}
  777. /* ═══════════════════════════════════════════════════════════════════
  778. APPS
  779. ═══════════════════════════════════════════════════════════════════ */
  780. .apps-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
  781. @media(max-width:768px){.apps-grid{grid-template-columns:1fr}}
  782. .app-card{
  783. background:var(--wr-card);border:1px solid var(--wr-line);
  784. border-radius:18px;padding:24px;
  785. display:flex;flex-direction:column;align-items:flex-start;
  786. transition:transform .2s,border-color .2s,box-shadow .2s;
  787. }
  788. .app-card:hover{transform:translateY(-3px);border-color:var(--wr-violet-2);box-shadow:var(--wr-shadow-hover);color:inherit;text-decoration:none}
  789. .app-card-icon{
  790. width:48px;height:48px;border-radius:14px;
  791. background:var(--wr-violet-soft);color:var(--wr-violet);
  792. display:inline-flex;align-items:center;justify-content:center;
  793. margin-bottom:18px;
  794. }
  795. .app-card-icon svg{width:22px;height:22px}
  796. .app-card-name{font-weight:500;font-size:18px;letter-spacing:-0.01em;color:var(--wr-ink);margin:0 0 6px}
  797. .app-card-desc{font-size:13px;line-height:1.5;color:var(--wr-muted);margin:0 0 16px;flex:1}
  798. .app-card-cta{font-size:12px;font-weight:600;color:var(--wr-violet);text-transform:uppercase;letter-spacing:.1em;display:inline-flex;align-items:center;gap:6px}
  799. .app-card-cta svg{width:11px;height:11px;transition:transform .15s}
  800. .app-card:hover .app-card-cta svg{transform:translateX(3px)}
  801. /* ═══════════════════════════════════════════════════════════════════
  802. KEYWORDS
  803. ═══════════════════════════════════════════════════════════════════ */
  804. .keywords-list{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:1200px;margin:0 auto}
  805. .keyword-pill{
  806. display:inline-flex;align-items:center;gap:8px;
  807. padding:9px 16px;border-radius:100px;
  808. background:var(--wr-card);border:1px solid var(--wr-line-2);
  809. color:var(--wr-ink-2);
  810. font-size:13.5px;font-weight:500;
  811. transition:transform .15s,border-color .15s,background .15s,color .15s,box-shadow .15s;
  812. }
  813. .keyword-pill:hover{transform:translateY(-2px);border-color:var(--wr-violet);background:var(--wr-violet-soft);color:var(--wr-violet-dark);text-decoration:none;box-shadow:0 4px 10px rgba(138,99,192,.12)}
  814. .keyword-pill-icon{font-size:14px;line-height:1}
  815. /* ═══════════════════════════════════════════════════════════════════
  816. OFFRES POPULAIRES
  817. ═══════════════════════════════════════════════════════════════════ */
  818. .listings-block{margin-bottom:32px}
  819. .listings-block:last-child{margin-bottom:0}
  820. .listings-block-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px;flex-wrap:wrap}
  821. .listings-block-title{
  822. display:inline-flex;align-items:center;gap:10px;
  823. font-weight:500;font-size:18px;letter-spacing:-0.005em;
  824. color:var(--wr-ink);margin:0;
  825. }
  826. .listings-block-icon{font-size:20px;line-height:1}
  827. .listings-block-link{
  828. display:inline-flex;align-items:center;gap:4px;
  829. padding:6px 12px;border-radius:100px;
  830. font-size:12px;font-weight:600;
  831. color:var(--wr-violet);
  832. text-transform:uppercase;letter-spacing:.06em;
  833. border:1px solid var(--wr-violet-soft);
  834. background:var(--wr-card);
  835. transition:background .15s,border-color .15s,transform .15s;
  836. }
  837. .listings-block-link:hover{background:var(--wr-violet-soft);border-color:var(--wr-violet);text-decoration:none;color:var(--wr-violet-dark);transform:translateX(2px)}
  838. .listings-block-link svg{width:11px;height:11px}
  839. .listings-jobs{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  840. @media(max-width:768px){.listings-jobs{grid-template-columns:1fr}}
  841. .listing-job{
  842. display:flex;align-items:center;gap:14px;
  843. background:var(--wr-card);border:1px solid var(--wr-line);
  844. border-radius:14px;padding:12px;
  845. transition:transform .15s,border-color .15s,box-shadow .15s;
  846. }
  847. .listing-job:hover{transform:translateY(-2px);border-color:var(--wr-violet-soft);box-shadow:var(--wr-shadow);color:inherit;text-decoration:none}
  848. .listing-job-logo{
  849. width:42px;height:42px;border-radius:11px;flex-shrink:0;
  850. background:var(--wr-violet-soft);color:var(--wr-violet);
  851. display:flex;align-items:center;justify-content:center;
  852. font-weight:700;font-size:14px;overflow:hidden;
  853. }
  854. .listing-job-logo img{width:100%;height:100%;object-fit:cover}
  855. .listing-job-info{flex:1;min-width:0}
  856. .listing-job-title{font-weight:600;font-size:13.5px;color:var(--wr-ink);margin:0 0 2px;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  857. .listing-job-meta{font-size:11.5px;color:var(--wr-muted);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  858. .listing-job-arrow{flex-shrink:0;color:var(--wr-muted-2);transition:color .15s,transform .15s}
  859. .listing-job-arrow svg{width:14px;height:14px}
  860. .listing-job:hover .listing-job-arrow{color:var(--wr-violet);transform:translateX(2px)}
  861. /* ═══════════════════════════════════════════════════════════════════
  862. ARTICLES — Liste sans miniatures (style identique aux jobs-card)
  863. ═══════════════════════════════════════════════════════════════════ */
  864. .articles-list{display:flex;flex-direction:column;gap:10px;max-width:1200px;margin:0 auto}
  865. .wr-article{
  866. background:var(--wr-card);border-radius:14px;padding:14px;
  867. box-shadow:0 0 16px 0 rgba(0,0,0,0.04);
  868. display:flex;align-items:center;gap:14px;
  869. text-decoration:none;color:inherit;
  870. transition:transform .15s,box-shadow .2s;
  871. }
  872. .wr-article:hover{
  873. transform:translateY(-1px);
  874. box-shadow:0 4px 20px rgba(138,99,192,.1);
  875. color:inherit;text-decoration:none;
  876. }
  877. .wr-article-logo{
  878. width:50px;height:50px;border-radius:12px;flex-shrink:0;
  879. background:linear-gradient(135deg,#EDE9FE,#DDD6FE);
  880. display:flex;align-items:center;justify-content:center;
  881. color:var(--wr-violet);overflow:hidden;
  882. }
  883. .wr-article-logo svg{width:24px;height:24px;opacity:.9}
  884. .wr-article-info{flex:1;min-width:0}
  885. .wr-article-title{
  886. font-size:14px;font-weight:700;color:var(--wr-ink);
  887. line-height:1.3;margin:0 0 4px;
  888. white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  889. }
  890. .wr-article-meta{
  891. font-size:12px;color:var(--wr-muted);
  892. white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  893. display:flex;align-items:center;gap:8px;margin:0;
  894. }
  895. .wr-article-meta-sep{display:inline-block;width:3px;height:3px;border-radius:50%;background:#D1D5DB;flex-shrink:0}
  896. .wr-article-badge{
  897. font-size:11px;font-weight:600;
  898. color:var(--wr-violet);background:var(--wr-violet-soft);
  899. padding:3px 9px;border-radius:100px;
  900. white-space:nowrap;flex-shrink:0;
  901. text-transform:uppercase;letter-spacing:.04em;
  902. }
  903. .wr-article-arrow{flex-shrink:0;color:var(--wr-muted-2);transition:color .15s,transform .15s}
  904. .wr-article:hover .wr-article-arrow{color:var(--wr-violet);transform:translateX(2px)}
  905. .wr-article-arrow svg{width:18px;height:18px}
  906. @media(max-width:540px){
  907. .wr-article{padding:12px;gap:10px}
  908. .wr-article-logo{width:42px;height:42px}
  909. .wr-article-logo svg{width:20px;height:20px}
  910. .wr-article-title{font-size:13px}
  911. .wr-article-meta{font-size:11px;gap:6px;flex-wrap:wrap;white-space:normal}
  912. .wr-article-badge{display:none}
  913. }
  914. .articles-cta{text-align:center;margin-top:36px}
  915. .articles-cta a{
  916. display:inline-flex;align-items:center;gap:8px;
  917. padding:12px 22px;border-radius:11px;
  918. background:var(--wr-violet);color:#fff;
  919. font-size:13px;font-weight:600;
  920. text-decoration:none;
  921. box-shadow:0 4px 12px rgba(138,99,192,.3);
  922. transition:background .15s,transform .15s,box-shadow .15s;
  923. }
  924. .articles-cta a:hover{background:var(--wr-violet-dark);transform:translateY(-2px);box-shadow:0 6px 18px rgba(138,99,192,.4);text-decoration:none;color:#fff}
  925. .articles-cta svg{width:12px;height:12px;transition:transform .15s}
  926. .articles-cta a:hover svg{transform:translateX(3px)}
  927. /* ═══════════════════════════════════════════════════════════════════
  928. CTA FINAL — Card violet plein avec eyebrow + 2 sous-cards
  929. ═══════════════════════════════════════════════════════════════════ */
  930. .final-card{
  931. position:relative;
  932. background:linear-gradient(135deg,#8A63C0 0%,#9D7BCC 100%);
  933. border-radius:28px;
  934. padding:48px 40px;
  935. color:#fff;overflow:hidden;
  936. box-shadow:0 20px 60px -12px rgba(138,99,192,.4);
  937. }
  938. @media(max-width:768px){.final-card{padding:32px 22px;border-radius:22px}}
  939. .final-eyebrow{
  940. display:inline-flex;align-items:center;gap:8px;
  941. padding:8px 18px;border-radius:100px;
  942. background:rgba(255,255,255,.2);
  943. color:#fff;
  944. font-size:12px;font-weight:700;
  945. text-transform:uppercase;letter-spacing:.12em;
  946. margin-bottom:20px;
  947. backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  948. }
  949. .final-eyebrow svg{width:13px;height:13px;fill:currentColor}
  950. .final-title{
  951. font-weight:800;font-size:28px;line-height:1.15;letter-spacing:-0.02em;
  952. color:#fff;margin:0 0 36px;
  953. max-width:780px;
  954. }
  955. @media(min-width:768px){.final-title{font-size:38px}}
  956. /* Grille 2 sous-cards */
  957. .final-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}
  958. @media(max-width:768px){.final-grid{grid-template-columns:1fr;gap:14px}}
  959. .final-sub{
  960. background:#fff;
  961. border-radius:18px;
  962. padding:28px;
  963. display:flex;flex-direction:column;
  964. }
  965. @media(max-width:768px){.final-sub{padding:22px}}
  966. .final-sub-head{display:flex;align-items:center;gap:14px;margin-bottom:18px}
  967. .final-sub-icon{
  968. width:44px;height:44px;border-radius:11px;
  969. background:var(--wr-violet-soft);color:var(--wr-violet);
  970. display:flex;align-items:center;justify-content:center;flex-shrink:0;
  971. }
  972. .final-sub-icon svg{width:22px;height:22px}
  973. .final-sub-label{
  974. font-size:12.5px;font-weight:700;
  975. color:var(--wr-violet);
  976. text-transform:uppercase;letter-spacing:.1em;
  977. }
  978. .final-sub-title{
  979. font-weight:800;font-size:18px;line-height:1.3;letter-spacing:-0.01em;
  980. color:var(--wr-ink);margin:0 0 10px;
  981. }
  982. .final-sub-desc{
  983. font-size:14px;line-height:1.55;color:var(--wr-muted);
  984. margin:0 0 24px;flex:1;
  985. }
  986. .final-sub-btn{
  987. display:flex;align-items:center;justify-content:center;gap:8px;
  988. background:var(--wr-violet);color:#fff;
  989. padding:14px 18px;border-radius:11px;
  990. font-size:14px;font-weight:700;
  991. text-decoration:none;
  992. transition:background .15s,transform .15s,box-shadow .15s;
  993. box-shadow:0 4px 12px rgba(138,99,192,.3);
  994. }
  995. .final-sub-btn:hover{
  996. background:var(--wr-violet-dark);color:#fff;
  997. transform:translateY(-2px);
  998. box-shadow:0 6px 18px rgba(138,99,192,.4);
  999. text-decoration:none;
  1000. }
  1001. .final-sub-btn svg{width:14px;height:14px;transition:transform .15s}
  1002. .final-sub-btn:hover svg{transform:translateX(3px)}
  1003. </style>
  1004. {% endblock css %}
  1005. {% block body %}
  1006. <div class="wr">
  1007. {# ═══════════════ HERO ═══════════════ #}
  1008. <section class="hero">
  1009. <div class="hero-inner">
  1010. <span class="hero-badge">
  1011. <span class="hero-badge-dot"></span>
  1012. {{ t.hero_eyebrow }}
  1013. </span>
  1014. <h1 class="hero-title">
  1015. <span class="hero-title-accent">{{ t.hero_title_accent }}</span> {{ t.hero_title_post }}<br>
  1016. <span class="hero-title-accent">{{ t.hero_title_accent2 }}</span> {{ t.hero_title_2 }}
  1017. </h1>
  1018. <p class="hero-lede">
  1019. {{ t.hero_lede_pre }}
  1020. <span class="hero-lede-accent">{{ t.hero_lede_brand }}</span>
  1021. {{ t.hero_lede_mid }}
  1022. <span class="hero-lede-accent">{{ t.hero_lede_word }}</span>
  1023. {{ t.hero_lede_post }}
  1024. </p>
  1025. {# Pills "Populaire" — AU-DESSUS de la recherche, cliquer remplit l'input #}
  1026. {% if popularKeywords is defined and popularKeywords|length > 0 %}
  1027. <div class="hero-popular">
  1028. <span class="hero-popular-label">{{ t.hero_popular_label }}</span>
  1029. {% for kw in popularKeywords|slice(0, 5) %}
  1030. <button type="button"
  1031. class="hero-popular-pill"
  1032. data-keyword="{{ kw.keyword }}"
  1033. data-label="{{ kw.label }}">
  1034. {% if kw.icon %}<span class="hero-popular-pill-icon">{{ kw.icon|raw }}</span>{% endif %}
  1035. <span>{{ kw.label }}</span>
  1036. </button>
  1037. {% endfor %}
  1038. </div>
  1039. {% endif %}
  1040. {# Recherche inline AJAX — style dashboard jobs #}
  1041. <div class="hero-search-wrap">
  1042. <div class="hero-search" id="wrHeroSearch"
  1043. data-search-url="{% if isFR %}{{ path('locale_api_jobs_search',{'_locale':'fr'}) }}{% else %}{{ path('api_jobs_search') }}{% endif %}"
  1044. data-jobs-list-url="{% if isFR %}{{ path('locale_whileresume_jobs_list',{'_locale':'fr'}) }}{% else %}{{ path('whileresume_jobs_list') }}{% endif %}">
  1045. <div class="hero-search-inner">
  1046. <span class="hero-search-icon">
  1047. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  1048. <circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/>
  1049. </svg>
  1050. </span>
  1051. <input type="text" name="q" id="wrHeroSearchInput" class="hero-search-input"
  1052. placeholder="{{ t.hero_search_placeholder }}"
  1053. autocomplete="off" />
  1054. <span class="hero-search-kbd">↵ {{ isFR ? 'Entrée' : 'Enter' }}</span>
  1055. <button type="button" class="hero-search-clear" id="wrHeroSearchClear" aria-label="{{ t.search_clear }}">
  1056. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
  1057. <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
  1058. </svg>
  1059. </button>
  1060. </div>
  1061. </div>
  1062. </div>
  1063. {# Liste de jobs — par défaut jobs aléatoires, remplacée par les résultats AJAX #}
  1064. {# Le compteur affiche le nombre total d'offres en ligne (toutes langues confondues) #}
  1065. {% set _heroCount = 0 %}
  1066. <div class="hero-default-jobs" id="wrHeroJobsList">
  1067. <div class="hero-jobs-header" id="wrHeroJobsHeader">
  1068. <span class="hero-jobs-count" id="wrHeroJobsCount">
  1069. <strong>{{ totalJobs ?? 0 }}</strong>{{ t.search_results_count }}
  1070. </span>
  1071. <a href="{% if isFR %}{{ path('locale_whileresume_jobs_list',{'_locale':'fr'}) }}{% else %}{{ path('whileresume_jobs_list') }}{% endif %}" class="hero-jobs-link" id="wrHeroJobsLink">
  1072. {{ t.search_view_all }}
  1073. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
  1074. <line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/>
  1075. </svg>
  1076. </a>
  1077. </div>
  1078. <div id="wrHeroJobsBody">
  1079. {% if randomJobs is defined and randomJobs|length > 0 %}
  1080. {% for j in randomJobs %}
  1081. {% if _heroCount < 6 %}
  1082. <a href="{% if j.locale == 'fr' %}{{ path('locale_cvs_application_job_show',{'_locale':app.request.locale,'slug':j.slug}) }}{% else %}{{ path('cvs_application_job_show',{'slug':j.slug}) }}{% endif %}" class="hero-default-job">
  1083. <div class="hero-default-job-logo">
  1084. {% if j.image and j.image.name %}
  1085. <img src="{{ vich_uploader_asset(j, 'imageFile') }}" alt="">
  1086. {% else %}
  1087. {{ j.companyName|default('?')|slice(0,1)|upper }}
  1088. {% endif %}
  1089. </div>
  1090. <div class="hero-default-job-info">
  1091. <h3 class="hero-default-job-title">{{ j.jobTitle }}</h3>
  1092. <p class="hero-default-job-meta">
  1093. {% if j.companyName %}<span>{{ j.companyName }}</span>{% endif %}
  1094. {% if j.city %}
  1095. <span class="hero-default-job-meta-sep"></span>
  1096. <span>{{ j.city }}{% if j.country %}, {{ j.country }}{% endif %}</span>
  1097. {% endif %}
  1098. {% if j.employmentType %}
  1099. <span class="hero-default-job-meta-sep"></span>
  1100. <span>{{ j.employmentType }}</span>
  1101. {% endif %}
  1102. </p>
  1103. </div>
  1104. <span class="hero-default-job-arrow">
  1105. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
  1106. </span>
  1107. </a>
  1108. {% set _heroCount = _heroCount + 1 %}
  1109. {% endif %}
  1110. {% endfor %}
  1111. {% endif %}
  1112. </div>
  1113. </div>
  1114. {# CTA pour utilisateurs non connectés : Inscription + Connexion #}
  1115. {% if app.user is null %}
  1116. <div class="hero-cta">
  1117. <a href="#register" class="hero-cta-btn">
  1118. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
  1119. <path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="8.5" cy="7" r="4"/><line x1="20" y1="8" x2="20" y2="14"/><line x1="23" y1="11" x2="17" y2="11"/>
  1120. </svg>
  1121. {{ t.hero_cta_signup }}
  1122. </a>
  1123. <a href="{% if isFR %}{{ path('locale_app_login',{'_locale':'fr'}) }}{% else %}{{ path('app_login') }}{% endif %}" class="hero-cta-btn">
  1124. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
  1125. <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/>
  1126. </svg>
  1127. {{ t.hero_cta_login }}
  1128. </a>
  1129. </div>
  1130. {% endif %}
  1131. </div>
  1132. </section>
  1133. {# ═══════════════ COMMENT ÇA MARCHE ═══════════════ #}
  1134. <section class="wr-section">
  1135. <div class="wr-container">
  1136. <div class="wr-section-head">
  1137. <h2 class="wr-title">{{ t.how_title }}</h2>
  1138. </div>
  1139. <div class="how-card">
  1140. <div class="how-step reveal" data-reveal-delay="1">
  1141. <div class="how-step-illu">
  1142. <img src="/uploads/rh/mascotte_register.png" alt="{{ t.how1_title }}" loading="lazy">
  1143. </div>
  1144. <h3 class="how-step-title">{{ t.how1_title }}</h3>
  1145. <p class="how-step-desc">{{ t.how1_desc }}</p>
  1146. </div>
  1147. <div class="how-step reveal" data-reveal-delay="2">
  1148. <div class="how-step-illu">
  1149. <img src="/uploads/rh/mascotte_upload2.png" alt="{{ t.how2_title }}" loading="lazy">
  1150. </div>
  1151. <h3 class="how-step-title">{{ t.how2_title }}</h3>
  1152. <p class="how-step-desc">{{ t.how2_desc }}</p>
  1153. </div>
  1154. <div class="how-step reveal" data-reveal-delay="3">
  1155. <div class="how-step-illu">
  1156. <img src="/uploads/rh/mascotte_reunion.png" alt="{{ t.how3_title }}" loading="lazy">
  1157. </div>
  1158. <h3 class="how-step-title">{{ t.how3_title }}</h3>
  1159. <p class="how-step-desc">{{ t.how3_desc }}</p>
  1160. </div>
  1161. </div>
  1162. </div>
  1163. </section>
  1164. {# ═══════════════ FEATURES 01-04 ═══════════════ #}
  1165. <section class="wr-section">
  1166. <div class="wr-container">
  1167. {# Feature 01 — Filtrage par critères #}
  1168. <div class="feat-block reveal">
  1169. <div class="feat-illu">
  1170. <img src="/uploads/rh/mascotte_filtrage3.png" alt="{{ t.feat1_title }}" loading="lazy">
  1171. </div>
  1172. <div class="feat-content">
  1173. <span class="feat-label">{{ t.feat1_label }}</span>
  1174. <h3 class="feat-title">{{ t.feat1_title }}</h3>
  1175. <div class="feat-desc">
  1176. <p>{{ t.feat1_p1|raw }}</p>
  1177. <p>{{ t.feat1_p2|raw }}</p>
  1178. </div>
  1179. <div class="feat-quote">
  1180. <p class="feat-quote-text">{{ t.feat1_quote }}</p>
  1181. <div class="feat-quote-author">
  1182. <p class="feat-quote-name">{{ t.feat1_author }}</p>
  1183. <p class="feat-quote-role">{{ t.feat1_role }}</p>
  1184. </div>
  1185. </div>
  1186. </div>
  1187. </div>
  1188. {# Feature 02 — Optimisation intelligente #}
  1189. <div class="feat-block reveal">
  1190. <div class="feat-illu">
  1191. <img src="/uploads/rh/mascotte_upload.png" alt="{{ t.feat2_title }}" loading="lazy">
  1192. </div>
  1193. <div class="feat-content">
  1194. <span class="feat-label">{{ t.feat2_label }}</span>
  1195. <h3 class="feat-title">{{ t.feat2_title }}</h3>
  1196. <div class="feat-desc">
  1197. <p>{{ t.feat2_p1|raw }}</p>
  1198. <p>{{ t.feat2_p2|raw }}</p>
  1199. </div>
  1200. <div class="feat-quote">
  1201. <p class="feat-quote-text">{{ t.feat2_quote }}</p>
  1202. <div class="feat-quote-author">
  1203. <p class="feat-quote-name">{{ t.feat2_author }}</p>
  1204. <p class="feat-quote-role">{{ t.feat2_role }}</p>
  1205. </div>
  1206. </div>
  1207. </div>
  1208. </div>
  1209. {% if app.user is null %}
  1210. {# ═════ INSCRIPTION (entre feat 02 et 03) ═════ #}
  1211. <div class="signup-card reveal reveal--scale" id="register">
  1212. <div class="signup-inner">
  1213. <div class="signup-text">
  1214. <span class="signup-eyebrow">
  1215. <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="8.5" cy="7" r="4"/><line x1="20" y1="8" x2="20" y2="14"/><line x1="23" y1="11" x2="17" y2="11"/></svg>
  1216. {{ t.signup_eyebrow }}
  1217. </span>
  1218. <h3 class="signup-title">{{ t.signup_title }}</h3>
  1219. <p class="signup-lede">{{ t.signup_lede }}</p>
  1220. <div class="signup-perks">
  1221. <span class="signup-perk">
  1222. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
  1223. {{ t.signup_perk1 }}
  1224. </span>
  1225. <span class="signup-perk">
  1226. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
  1227. {{ t.signup_perk2 }}
  1228. </span>
  1229. <span class="signup-perk">
  1230. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
  1231. {{ t.signup_perk3 }}
  1232. </span>
  1233. </div>
  1234. </div>
  1235. {% if form is defined %}
  1236. {# Cas 1 : le controller passe le formulaire Symfony — rendu via form_widget #}
  1237. {{ form_start(form, {'attr': {'class': 'signup-form', 'novalidate': 'novalidate'}}) }}
  1238. {{ form_errors(form) }}
  1239. {% for message in app.flashes('danger') %}
  1240. <p class="signup-form-error">{{ message }}</p>
  1241. {% endfor %}
  1242. <div class="signup-field">
  1243. {{ form_widget(form.email, {'attr': {'placeholder': t.signup_email_ph}}) }}
  1244. </div>
  1245. <div class="signup-row">
  1246. <div class="signup-field">
  1247. {{ form_widget(form.password.first, {'attr': {'placeholder': t.signup_pass_ph}}) }}
  1248. </div>
  1249. <div class="signup-field">
  1250. {{ form_widget(form.password.second, {'attr': {'placeholder': t.signup_pass2_ph}}) }}
  1251. </div>
  1252. </div>
  1253. <label class="signup-terms">
  1254. {{ form_widget(form.acceptTerm) }}
  1255. <span>
  1256. {{ t.signup_terms_pre }}
  1257. <a href="{% if isFR %}/fr/protections-donnees-candidats{% else %}/data-protection-candidates{% endif %}" target="_blank" rel="noopener">{{ t.signup_terms_link }}</a>.
  1258. </span>
  1259. </label>
  1260. {% if form.recaptcha is defined %}
  1261. <div class="signup-recaptcha">{{ form_widget(form.recaptcha) }}</div>
  1262. {% endif %}
  1263. <button type="submit" class="signup-submit">
  1264. {{ t.signup_btn }}
  1265. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  1266. </button>
  1267. {{ form_rest(form) }}
  1268. {{ form_end(form) }}
  1269. {% endif %}
  1270. </div>
  1271. </div>
  1272. {% endif %}
  1273. {# Feature 03 — Recherche qualifiée #}
  1274. <div class="feat-block reveal">
  1275. <div class="feat-illu">
  1276. <img src="/uploads/rh/mascotte_register.png" alt="{{ t.feat3_title }}" loading="lazy">
  1277. </div>
  1278. <div class="feat-content">
  1279. <span class="feat-label">{{ t.feat3_label }}</span>
  1280. <h3 class="feat-title">{{ t.feat3_title }}</h3>
  1281. <div class="feat-desc">
  1282. <p>{{ t.feat3_p1|raw }}</p>
  1283. <p>{{ t.feat3_p2|raw }}</p>
  1284. </div>
  1285. <div class="feat-quote">
  1286. <p class="feat-quote-text">{{ t.feat3_quote }}</p>
  1287. <div class="feat-quote-author">
  1288. <p class="feat-quote-name">{{ t.feat3_author }}</p>
  1289. <p class="feat-quote-role">{{ t.feat3_role }}</p>
  1290. </div>
  1291. </div>
  1292. </div>
  1293. </div>
  1294. {# Feature 04 — Contact direct qualifié #}
  1295. <div class="feat-block reveal">
  1296. <div class="feat-illu">
  1297. <img src="/uploads/rh/mascotte_reunion.png" alt="{{ t.feat4_title }}" loading="lazy">
  1298. </div>
  1299. <div class="feat-content">
  1300. <span class="feat-label">{{ t.feat4_label }}</span>
  1301. <h3 class="feat-title">{{ t.feat4_title }}</h3>
  1302. <div class="feat-desc">
  1303. <p>{{ t.feat4_p1|raw }}</p>
  1304. <p>{{ t.feat4_p2|raw }}</p>
  1305. </div>
  1306. <div class="feat-quote">
  1307. <p class="feat-quote-text">{{ t.feat4_quote }}</p>
  1308. <div class="feat-quote-author">
  1309. <p class="feat-quote-name">{{ t.feat4_author }}</p>
  1310. <p class="feat-quote-role">{{ t.feat4_role }}</p>
  1311. </div>
  1312. </div>
  1313. </div>
  1314. </div>
  1315. </div>
  1316. </section>
  1317. {# ═══════════════ APPS ═══════════════ #}
  1318. <section class="wr-section">
  1319. <div class="wr-container">
  1320. <div class="apps-grid">
  1321. <a href="{{ isFR ? (ios_fr|default('#')) : (ios_us|default('#')) }}" class="app-card">
  1322. <span class="app-card-icon">
  1323. <svg viewBox="0 0 24 24" fill="currentColor"><path d="M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z"/></svg>
  1324. </span>
  1325. <h3 class="app-card-name">{{ t.apps_ios }}</h3>
  1326. <p class="app-card-desc">{{ t.apps_ios_desc }}</p>
  1327. <span class="app-card-cta">App Store
  1328. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  1329. </span>
  1330. </a>
  1331. <a href="{{ isFR ? (android_fr|default('#')) : (android_us|default('#')) }}" class="app-card">
  1332. <span class="app-card-icon">
  1333. <svg viewBox="0 0 24 24" fill="currentColor"><path d="M17.523 15.34c-.583 0-1.06-.477-1.06-1.06 0-.582.477-1.06 1.06-1.06.583 0 1.06.478 1.06 1.06 0 .583-.477 1.06-1.06 1.06m-11.046 0c-.583 0-1.06-.477-1.06-1.06 0-.582.477-1.06 1.06-1.06.583 0 1.06.478 1.06 1.06 0 .583-.477 1.06-1.06 1.06m11.427-6.176l2.114-3.66a.439.439 0 0 0-.16-.6.439.439 0 0 0-.6.16l-2.142 3.71a13.07 13.07 0 0 0-5.116-1.034c-1.823 0-3.55.376-5.116 1.034l-2.14-3.71a.439.439 0 1 0-.76.44l2.113 3.66C2.486 10.78.659 13.658.5 17h23c-.16-3.342-1.987-6.22-5.595-7.836"/></svg>
  1334. </span>
  1335. <h3 class="app-card-name">{{ t.apps_android }}</h3>
  1336. <p class="app-card-desc">{{ t.apps_android_desc }}</p>
  1337. <span class="app-card-cta">Google Play
  1338. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  1339. </span>
  1340. </a>
  1341. <a href="{% if app.request.locale == 'en' %}{{ path('whileresume_homepage') }}{% else %}{{ path('locale_whileresume_homepage',{'_locale':app.request.locale}) }}{% endif %}#register" class="app-card">
  1342. <span class="app-card-icon">
  1343. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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>
  1344. </span>
  1345. <h3 class="app-card-name">{{ t.apps_web }}</h3>
  1346. <p class="app-card-desc">{{ t.apps_web_desc }}</p>
  1347. <span class="app-card-cta">whileresume.com
  1348. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  1349. </span>
  1350. </a>
  1351. </div>
  1352. </div>
  1353. </section>
  1354. {# ═══════════════ ARTICLES ═══════════════ #}
  1355. {% if articles is defined and articles|length > 0 %}
  1356. <section class="wr-section">
  1357. <div class="wr-container">
  1358. <div class="wr-section-head">
  1359. <h2 class="wr-title wr-title--sm">{{ t.articles_title }}</h2>
  1360. </div>
  1361. <div class="articles-list">
  1362. {% for a in articles|slice(0,6) %}
  1363. {% set prefix = "" %}
  1364. {% set urlA = path('cvs_website_article',{'slug': a.slug}) %}
  1365. {% if app.request.locale != default_locale %}
  1366. {% set urlA = path('locale_cvs_website_article',{'_locale':app.request.locale,'slug': a.slug}) %}
  1367. {% set prefix = "/" ~ app.request.locale %}
  1368. {% endif %}
  1369. {% if a.pageslug3 is not empty %}
  1370. {% set urlA = prefix ~ '/' ~ a.pageslug ~ '/' ~ a.pageslug2 ~ '/' ~ a.pageslug3 %}
  1371. {% elseif a.pageslug2 is not empty %}
  1372. {% set urlA = prefix ~ '/' ~ a.pageslug ~ '/' ~ a.pageslug2 %}
  1373. {% elseif a.pageslug is not empty %}
  1374. {% set urlA = prefix ~ '/' ~ a.pageslug %}
  1375. {% endif %}
  1376. <a href="{{ urlA }}" class="wr-article">
  1377. <div class="wr-article-logo">
  1378. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  1379. <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/>
  1380. <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/>
  1381. </svg>
  1382. </div>
  1383. <div class="wr-article-info">
  1384. <h3 class="wr-article-title">{{ a.title }}</h3>
  1385. <div class="wr-article-meta">
  1386. {% if a.subtitle is not empty %}
  1387. <span>{{ a.subtitle|length > 60 ? a.subtitle|slice(0,60) ~ '…' : a.subtitle }}</span>
  1388. {% endif %}
  1389. </div>
  1390. </div>
  1391. <span class="wr-article-badge">{{ t.read_article }}</span>
  1392. <span class="wr-article-arrow">
  1393. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  1394. <polyline points="9 18 15 12 9 6"/>
  1395. </svg>
  1396. </span>
  1397. </a>
  1398. {% endfor %}
  1399. </div>
  1400. <div class="articles-cta">
  1401. <a href="{% if isFR %}{{ path('locale_cvs_website_articles',{'_locale':'fr'}) }}{% else %}{{ path('cvs_website_articles') }}{% endif %}">
  1402. {{ t.articles_view_all }}
  1403. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  1404. </a>
  1405. </div>
  1406. </div>
  1407. </section>
  1408. {% endif %}
  1409. {# ═══════════════ CTA FINAL ═══════════════ #}
  1410. {% if app.user is null %}
  1411. <section class="wr-section">
  1412. <div class="wr-container">
  1413. <div class="final-card">
  1414. <h2 class="final-title">{{ t.final_title }}</h2>
  1415. <div class="final-grid">
  1416. {# Recruteur #}
  1417. <div class="final-sub">
  1418. <div class="final-sub-head">
  1419. <span class="final-sub-icon">
  1420. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
  1421. <rect x="2" y="7" width="20" height="14" rx="2" ry="2"/>
  1422. <path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>
  1423. </svg>
  1424. </span>
  1425. <span class="final-sub-label">{{ t.final_recruiter_label }}</span>
  1426. </div>
  1427. <h3 class="final-sub-title">{{ t.final_recruiter_title }}</h3>
  1428. <p class="final-sub-desc">{{ t.final_recruiter_desc }}</p>
  1429. <a href="{{ path('whileresume_business_' ~ app.request.locale) }}" class="final-sub-btn">
  1430. {{ t.final_recruiter }}
  1431. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  1432. </a>
  1433. </div>
  1434. {# Candidat #}
  1435. <div class="final-sub">
  1436. <div class="final-sub-head">
  1437. <span class="final-sub-icon">
  1438. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
  1439. <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
  1440. <circle cx="12" cy="7" r="4"/>
  1441. </svg>
  1442. </span>
  1443. <span class="final-sub-label">{{ t.final_candidate_label }}</span>
  1444. </div>
  1445. <h3 class="final-sub-title">{{ t.final_candidate_title }}</h3>
  1446. <p class="final-sub-desc">{{ t.final_candidate_desc }}</p>
  1447. <a href="{% if app.request.locale == 'en' %}{{ path('whileresume_homepage') }}{% else %}{{ path('locale_whileresume_homepage',{'_locale':app.request.locale}) }}{% endif %}#register" class="final-sub-btn">
  1448. {{ t.final_candidate }}
  1449. <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
  1450. </a>
  1451. </div>
  1452. </div>
  1453. </div>
  1454. </div>
  1455. </section>
  1456. {% endif %}
  1457. </div>
  1458. {% endblock body %}
  1459. {% block footer_js %}
  1460. {{ parent() }}
  1461. <script>
  1462. (function(){
  1463. var search = document.getElementById('wrHeroSearch');
  1464. var input = document.getElementById('wrHeroSearchInput');
  1465. var clearBtn = document.getElementById('wrHeroSearchClear');
  1466. var jobsBody = document.getElementById('wrHeroJobsBody');
  1467. var countEl = document.getElementById('wrHeroJobsCount');
  1468. var linkEl = document.getElementById('wrHeroJobsLink');
  1469. if (!search || !input || !jobsBody) return;
  1470. var searchUrl = search.dataset.searchUrl;
  1471. var jobsListUrl = search.dataset.jobsListUrl;
  1472. // On garde l'état initial pour pouvoir le restaurer
  1473. var defaultBodyHtml = jobsBody.innerHTML;
  1474. var defaultCountHtml = countEl ? countEl.innerHTML : '';
  1475. var defaultLinkHref = linkEl ? linkEl.getAttribute('href') : jobsListUrl;
  1476. var debounceTimer = null;
  1477. var currentRequest = null;
  1478. var lastQuery = '';
  1479. var T = {
  1480. loading: '{{ t.search_loading|escape('js') }}',
  1481. empty: '{{ t.search_no_results|escape('js') }}',
  1482. emptyHint: '{{ t.search_no_results_hint|escape('js') }}',
  1483. count: '{{ t.search_results_count|escape('js') }}',
  1484. viewAll: '{{ t.search_view_all|escape('js') }}',
  1485. view: '{{ t.search_view_offer|escape('js') }}'
  1486. };
  1487. function escHtml(s){
  1488. if (s == null) return '';
  1489. return String(s).replace(/[&<>"']/g, function(c){
  1490. return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c];
  1491. });
  1492. }
  1493. function setHeaderCount(total){
  1494. if (!countEl) return;
  1495. countEl.innerHTML = '<strong>' + total + '</strong>' + escHtml(T.count);
  1496. }
  1497. function setHeaderLink(href){
  1498. if (!linkEl) return;
  1499. linkEl.setAttribute('href', href);
  1500. }
  1501. function setLoading(){
  1502. jobsBody.innerHTML =
  1503. '<div class="hero-jobs-loading">' +
  1504. '<span class="hero-jobs-spinner"></span>' +
  1505. '<span>' + escHtml(T.loading) + '</span>' +
  1506. '</div>';
  1507. }
  1508. function setEmpty(){
  1509. jobsBody.innerHTML =
  1510. '<div class="hero-jobs-empty">' +
  1511. '<div class="hero-jobs-empty-icon">' +
  1512. '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' +
  1513. '<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>' +
  1514. '</svg>' +
  1515. '</div>' +
  1516. '<p class="hero-jobs-empty-title">' + escHtml(T.empty) + '</p>' +
  1517. '<p class="hero-jobs-empty-hint">' + escHtml(T.emptyHint) + '</p>' +
  1518. '</div>';
  1519. }
  1520. function restoreDefault(){
  1521. jobsBody.innerHTML = defaultBodyHtml;
  1522. if (countEl) countEl.innerHTML = defaultCountHtml;
  1523. if (linkEl) linkEl.setAttribute('href', defaultLinkHref);
  1524. }
  1525. function renderResults(payload, query){
  1526. var jobs = (payload && payload.jobs) || [];
  1527. var total = (payload && typeof payload.total === 'number') ? payload.total : jobs.length;
  1528. setHeaderCount(total);
  1529. setHeaderLink(jobsListUrl + '?q=' + encodeURIComponent(query));
  1530. if (!jobs.length){
  1531. setEmpty();
  1532. return;
  1533. }
  1534. var html = '';
  1535. jobs.slice(0, 6).forEach(function(j){
  1536. var title = j.jobTitle || j.title || '';
  1537. var company = j.companyName || j.company || '';
  1538. var city = j.city || '';
  1539. var country = j.country || '';
  1540. var et = j.employmentType || '';
  1541. var img = j.image || j.imageUrl || '';
  1542. var url = j.url || (jobsListUrl + '?q=' + encodeURIComponent(query));
  1543. var initial = (company || title || '?').charAt(0).toUpperCase();
  1544. var location = city + (country ? ', ' + country : '');
  1545. var metaParts = [];
  1546. if (company) metaParts.push('<span>' + escHtml(company) + '</span>');
  1547. if (location) metaParts.push('<span class="hero-default-job-meta-sep"></span><span>' + escHtml(location) + '</span>');
  1548. if (et) metaParts.push('<span class="hero-default-job-meta-sep"></span><span>' + escHtml(et) + '</span>');
  1549. html +=
  1550. '<a href="' + escHtml(url) + '" class="hero-default-job">' +
  1551. '<div class="hero-default-job-logo">' +
  1552. (img
  1553. ? '<img src="' + escHtml(img) + '" alt="">'
  1554. : escHtml(initial)) +
  1555. '</div>' +
  1556. '<div class="hero-default-job-info">' +
  1557. '<h3 class="hero-default-job-title">' + escHtml(title) + '</h3>' +
  1558. '<p class="hero-default-job-meta">' + metaParts.join('') + '</p>' +
  1559. '</div>' +
  1560. '<span class="hero-default-job-arrow">' +
  1561. '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>' +
  1562. '</span>' +
  1563. '</a>';
  1564. });
  1565. jobsBody.innerHTML = html;
  1566. }
  1567. function doSearch(query){
  1568. if (currentRequest && currentRequest.abort) {
  1569. try { currentRequest.abort(); } catch(e){}
  1570. }
  1571. setLoading();
  1572. var url = searchUrl + (searchUrl.indexOf('?') > -1 ? '&' : '?') + 'q=' + encodeURIComponent(query);
  1573. var ctrl = (typeof AbortController !== 'undefined') ? new AbortController() : null;
  1574. currentRequest = ctrl;
  1575. fetch(url, { headers: { 'Accept': 'application/json' }, signal: ctrl ? ctrl.signal : undefined })
  1576. .then(function(r){ return r.ok ? r.json() : Promise.reject(r.status); })
  1577. .then(function(data){ renderResults(data, query); })
  1578. .catch(function(err){
  1579. if (err && err.name === 'AbortError') return;
  1580. setEmpty();
  1581. });
  1582. }
  1583. // Input live (debounce 280ms)
  1584. input.addEventListener('input', function(){
  1585. var q = input.value.trim();
  1586. clearBtn.classList.toggle('is-visible', q.length > 0);
  1587. if (debounceTimer) clearTimeout(debounceTimer);
  1588. if (q.length < 2){
  1589. restoreDefault();
  1590. lastQuery = '';
  1591. return;
  1592. }
  1593. if (q === lastQuery) return;
  1594. debounceTimer = setTimeout(function(){
  1595. lastQuery = q;
  1596. doSearch(q);
  1597. }, 280);
  1598. });
  1599. // Enter → page de résultats complète
  1600. input.addEventListener('keydown', function(e){
  1601. if (e.key === 'Enter'){
  1602. e.preventDefault();
  1603. var q = input.value.trim();
  1604. if (!q) return;
  1605. window.location.href = jobsListUrl + '?q=' + encodeURIComponent(q);
  1606. }
  1607. if (e.key === 'Escape'){
  1608. input.value = '';
  1609. clearBtn.classList.remove('is-visible');
  1610. restoreDefault();
  1611. lastQuery = '';
  1612. input.blur();
  1613. }
  1614. });
  1615. // Clear
  1616. clearBtn.addEventListener('click', function(){
  1617. input.value = '';
  1618. clearBtn.classList.remove('is-visible');
  1619. restoreDefault();
  1620. lastQuery = '';
  1621. input.focus();
  1622. });
  1623. // Pills "Populaire" — au clic, on remplit l'input et on lance la recherche
  1624. document.querySelectorAll('.hero-popular-pill').forEach(function(pill){
  1625. pill.addEventListener('click', function(){
  1626. var keyword = pill.dataset.keyword || pill.dataset.label || '';
  1627. if (!keyword) return;
  1628. // Visuel actif
  1629. document.querySelectorAll('.hero-popular-pill').forEach(function(p){ p.classList.remove('is-active'); });
  1630. pill.classList.add('is-active');
  1631. input.value = keyword;
  1632. clearBtn.classList.add('is-visible');
  1633. lastQuery = keyword;
  1634. doSearch(keyword);
  1635. input.focus();
  1636. });
  1637. });
  1638. })();
  1639. /* ═══ Reveal au scroll (Intersection Observer) ═══ */
  1640. (function(){
  1641. var els = document.querySelectorAll('.reveal');
  1642. if (!els.length) return;
  1643. if (!('IntersectionObserver' in window)){
  1644. // Fallback : tout révéler
  1645. els.forEach(function(el){ el.classList.add('is-revealed'); });
  1646. return;
  1647. }
  1648. var io = new IntersectionObserver(function(entries){
  1649. entries.forEach(function(entry){
  1650. if (entry.isIntersecting){
  1651. entry.target.classList.add('is-revealed');
  1652. io.unobserve(entry.target);
  1653. }
  1654. });
  1655. }, { threshold: 0.12, rootMargin: '0px 0px -60px 0px' });
  1656. els.forEach(function(el){ io.observe(el); });
  1657. })();
  1658. </script>
  1659. {% endblock footer_js %}