{% extends 'application/whileresume/website/candidates/layout-social.html.twig' %}{# ═══════════════════════════════════════════════════════════════════ STRINGS bilingues═══════════════════════════════════════════════════════════════════ #}{% set isFR = app.request.locale == 'fr' %}{% set t = { hero_eyebrow: isFR ? 'Plateforme d’emploi nouvelle génération' : 'A new-generation job platform', hero_title_1: isFR ? 'Faites parler' : 'Let your', hero_title_2: isFR ? 'votre CV.' : 'CV speak.', hero_title_3: isFR ? 'On s’occupe du reste.' : 'We handle the rest.', hero_lede: isFR ? 'Whileresume met en relation les talents avec les entreprises qui recrutent — sans candidature à rallonge, sans CV à refaire 10 fois. Likez, matchez, échangez.' : 'Whileresume connects talent with hiring companies — no endless applications, no CVs rewritten ten times. Like, match, chat.', hero_search_placeholder: isFR ? 'Un poste, une ville, une entreprise…' : 'A job, a city, a company…', hero_search_button: isFR ? 'Rechercher' : 'Search', hero_byline_jobs: isFR ? 'offres en ligne' : 'jobs online', hero_byline_apps: isFR ? 'iOS · Android · Web' : 'iOS · Android · Web', hero_byline_free: isFR ? 'gratuit pour les candidats' : 'free for candidates', search_loading: isFR ? 'Recherche…' : 'Searching…', search_no_results: isFR ? 'Aucune offre ne correspond à votre recherche' : 'No job matches your search', search_no_results_hint: isFR ? 'Essayez avec d’autres mots-clés' : 'Try other keywords', search_results_count: isFR ? 'offres trouvées' : 'jobs found', search_view_all: isFR ? 'Voir toutes les offres' : 'See all jobs', search_view_offer: isFR ? 'Voir l’offre' : 'View job', search_clear: isFR ? 'Effacer' : 'Clear', paths_eyebrow: isFR ? 'Trois manières d’entrer' : 'Three ways in', paths_title: isFR ? 'Choisissez votre point de départ' : 'Choose your starting point', paths_lede: isFR ? 'Que vous arriviez avec un CV bien rangé ou simplement avec l’envie de bouger, il existe une porte qui vous correspond.' : 'Whether you arrive with a polished CV or just the urge to move on, there’s a door for you.', path1_label: isFR ? 'J’ai déjà un CV' : 'I have a CV', path1_title: isFR ? 'Envoyez. On lit. On améliore.' : 'Send. Read. Refine.', path1_desc: isFR ? 'Vous déposez votre CV, on en extrait les compétences, on identifie ce qui peut être renforcé, et on régénère deux versions propres dans la langue et le thème de votre choix.' : 'You upload your CV, we extract your skills, identify what can be strengthened, and regenerate two clean versions in the language and theme of your choice.', path1_cta: isFR ? 'Déposer mon CV' : 'Upload my CV', path2_label: isFR ? 'Je pars de zéro' : 'Starting fresh', path2_title: isFR ? 'Quelques étapes. Un beau CV.' : 'A few steps. A clean CV.', path2_desc: isFR ? 'Pas de CV ? On vous accompagne dans un tunnel guidé. À la fin, vous repartez avec un document construit, lisible, prêt à être envoyé — ou à laisser parler pour vous, ici.' : 'No CV? We guide you through. At the end, you walk out with a structured, readable document, ready to send — or to let it speak for you, here.', path2_cta: isFR ? 'Construire mon CV' : 'Build my CV', path3_label: isFR ? 'Je veux d’abord regarder' : 'Browse first', path3_title: isFR ? 'Liker, c’est déjà commencer.' : 'Liking is already starting.', path3_desc: isFR ? 'Parcourez les offres et les entreprises. Likez celles qui vous parlent. On en déduit vos goûts, on vous propose mieux, et les recruteurs intéressés peuvent vous trouver.' : 'Browse jobs and companies. Like the ones that speak to you. We learn your taste, suggest better ones, and interested recruiters find you.', path3_cta: isFR ? 'Voir les offres' : 'See jobs', how_eyebrow: isFR ? 'Comment ça marche' : 'How it works', how_title: isFR ? 'Quatre temps, un mouvement.' : 'Four moves, one motion.', how_lede: isFR ? 'On a réduit le parcours à l’essentiel. Pas de remplissage, pas de vous demander deux fois la même chose.' : 'We pared the journey down to the essentials. No filler, no asking the same thing twice.', step1_title: isFR ? 'Vous racontez' : 'You tell', step1_desc: isFR ? 'CV uploadé ou tunnel guidé. On collecte ce qu’il faut savoir : compétences, parcours, envies, langues.' : 'CV uploaded or guided tunnel. We collect what matters: skills, experience, wishes, languages.', step2_title: isFR ? 'On analyse' : 'We analyze', step2_desc: isFR ? 'Notre intelligence relit votre profil. Forces, axes d’amélioration : vous recevez un retour clair.' : 'Our intelligence re-reads your profile. Strengths, areas to improve: you get a clear report.', step3_title: isFR ? 'On génère' : 'We generate', step3_desc: isFR ? 'Votre CV est généré dans deux thèmes, plusieurs couleurs, plusieurs langues. Téléchargeable à tout moment.' : 'Your CV is generated in two themes, multiple colors, multiple languages. Downloadable any time.', step4_title: isFR ? 'On vous expose' : 'We expose you', step4_desc: isFR ? 'Votre profil devient visible des recruteurs qui cherchent exactement votre type de talent.' : 'Your profile becomes visible to recruiters looking for exactly your type of talent.', apps_eyebrow: isFR ? 'Disponible partout' : 'Available everywhere', apps_title: isFR ? 'Trois plateformes, une seule expérience' : 'Three platforms, one experience', apps_lede: isFR ? 'Vos préférences vous suivent. Likez une offre dans le métro, envoyez votre CV depuis votre canapé.' : 'Your preferences follow you. Like an offer on the subway, send your CV from the couch.', apps_ios: 'iOS', apps_android: 'Android', apps_web: isFR ? 'Web' : 'Web', apps_ios_desc: isFR ? 'Téléchargez sur l’App Store' : 'Download on the App Store', apps_android_desc: isFR ? 'Téléchargez sur Google Play' : 'Get it on Google Play', apps_web_desc: isFR ? 'Connectez-vous depuis le navigateur' : 'Log in from your browser', match_eyebrow: isFR ? 'Le match ne se force pas' : 'A match cannot be forced', match_title: isFR ? 'Likez. Matchez. Échangez.' : 'Like. Match. Chat.', match_lede: isFR ? 'Vous likez ce qui vous plaît, on apprend, et les entreprises intéressées passent la première.' : 'You like what catches your eye, we learn, and interested companies make the first move.', match_b1_title: isFR ? 'Likez ce qui vous parle' : 'Like what speaks to you', match_b1_desc: isFR ? 'Offres, entreprises, recruteurs. On retient tout pour mieux vous connaître.' : 'Jobs, companies, recruiters. We remember everything to know you better.', match_b2_title: isFR ? 'Recommandations sur mesure' : 'Tailored recommendations', match_b2_desc: isFR ? 'Plus vous likez, plus on vous propose des offres alignées avec votre profil.' : 'The more you like, the more we suggest offers aligned with your profile.', match_b3_title: isFR ? 'Les recruteurs viennent à vous' : 'Recruiters come to you', match_b3_desc: isFR ? 'Quand votre profil match, c’est l’entreprise qui passe la première.' : 'When your profile matches, the company makes the first move.', match_b4_title: isFR ? 'Offres externes incluses' : 'External offers included', match_b4_desc: isFR ? 'On indexe aussi des offres externes pour maximiser vos chances. Lien direct vers le site de l’employeur.' : 'We also index external offers to maximize your chances. Direct link to the employer’s site.', keywords_title: isFR ? 'Cherchez par domaine' : 'Search by field', keywords_lede: isFR ? 'Une porte d’entrée par métier' : 'One door per craft', popular_title: isFR ? 'Offres populaires' : 'Popular jobs', popular_lede: isFR ? 'Une sélection d’offres ouvertes en ce moment, par catégorie' : 'A selection of currently open positions, by category', btn_more: isFR ? 'Tout voir' : 'See all', articles_title: isFR ? 'Conseils, ressources & guides' : 'Advice, resources & guides', articles_lede: isFR ? 'Pour rebondir, négocier, postuler mieux.' : 'To bounce back, negotiate and apply better.', articles_view_all: isFR ? 'Voir tous les articles' : 'See all articles', read_article: isFR ? 'Lire' : 'Read', final_title: isFR ? 'Prêt à propulser votre carrière ?' : 'Ready to take your career further?', final_subtitle: isFR ? 'Rejoignez celles et ceux qui ont déjà tourné la page.' : 'Join those who have already turned the page.', final_candidate: isFR ? 'Je suis candidat·e' : 'I’m a candidate', final_recruiter: isFR ? 'Je recrute' : 'I’m hiring'} %}{% block title %}{{ page.shortTitle }}{% endblock %}{% block description %}{{ page.shortDescription }}{% endblock %}{% block robots %}{{ page.robots }}{% endblock %}{% block canonical %}{% include "/vitrine/lexend/components/languages/canonical_classic.html.twig" %}{% endblock %}{% block css %} {{ parent() }} <style> /* ═══════════════════════════════════════════════════════════════════ VARIABLES ═══════════════════════════════════════════════════════════════════ */ :root{ --wr-bg:#FBFCFE; --wr-card:#FFFFFF; --wr-violet:#8A63C0; --wr-violet-2:#A98AD3; --wr-violet-soft:#F2EDFA; --wr-violet-softer:#F8F4FD; --wr-violet-dark:#6B47A6; --wr-ink:#1E1B2E; --wr-ink-2:#374151; --wr-muted:#6B7280; --wr-muted-2:#9CA3AF; --wr-line:#EEF1F7; --wr-line-2:#E5E9F0; --wr-shadow:0 1px 2px rgba(30,27,46,.04),0 4px 16px rgba(30,27,46,.04); --wr-shadow-hover:0 4px 8px rgba(138,99,192,.08),0 12px 32px rgba(138,99,192,.1); } /* ═══════════════════════════════════════════════════════════════════ PLEINE LARGEUR — On retire la réservation d'espace de la sidebar droite ═══════════════════════════════════════════════════════════════════ */ body .main-content.right-chat-active{padding-right:0!important} body .main-content{padding-right:0!important} body .right-chat{display:none!important} body .middle-sidebar-bottom .middle-sidebar-left{padding-right:0!important;max-width:none!important;width:100%!important} body .middle-sidebar-bottom{max-width:none!important} .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} @media(max-width:991px){.wr{margin:0 -15px}} .wr *{box-sizing:border-box} .wr a{color:inherit;text-decoration:none} /* ═══════════════════════════════════════════════════════════════════ SECTIONS GENERIC — Fond UNIFIÉ partout (pas d'alternance) ═══════════════════════════════════════════════════════════════════ */ .wr-section{padding:80px 32px;background:var(--wr-bg);position:relative} .wr-section--tight{padding:48px 32px} @media(max-width:768px){.wr-section{padding:56px 20px}.wr-section--tight{padding:36px 20px}} /* Filet décoratif au lieu d'un changement de couleur */ .wr-section + .wr-section::before{ content:""; position:absolute;top:0;left:50%;transform:translateX(-50%); width:80px;height:1px; background:linear-gradient(90deg,transparent,var(--wr-line-2),transparent); } .wr-container{max-width:1200px;margin:0 auto;position:relative} /* ═══ Eyebrow ═══ */ .wr-eyebrow{ display:inline-flex;align-items:center;gap:8px; padding:6px 14px;border-radius:100px; background:var(--wr-violet-soft); color:var(--wr-violet-dark); font-size:11.5px;font-weight:600; text-transform:uppercase;letter-spacing:.12em; margin-bottom:22px; } .wr-eyebrow-dot{width:6px;height:6px;border-radius:50%;background:var(--wr-violet);animation:wrPulse 2.4s ease-in-out infinite} @keyframes wrPulse{0%,100%{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}} /* ═══ Titres — THIN + LARGE ═══ */ .wr-title{ font-family:inherit; font-weight:500; font-size:36px;line-height:1.1;letter-spacing:-0.03em; color:var(--wr-ink); margin:0 auto 16px; max-width:920px; } @media(min-width:768px){.wr-title{font-size:48px}} @media(min-width:1024px){.wr-title{font-size:58px}} .wr-title--sm{font-size:30px} @media(min-width:768px){.wr-title--sm{font-size:38px}} .wr-title em{font-style:normal;font-weight:600;color:var(--wr-violet)} .wr-lede{ font-size:17px;line-height:1.55;font-weight:400; color:var(--wr-ink-2); margin:0 auto;max-width:680px; } .wr-section-head{text-align:center;margin-bottom:56px} /* ═══════════════════════════════════════════════════════════════════ HERO — Plein texte, fond uni, animation discrète ═══════════════════════════════════════════════════════════════════ */ .hero{ position:relative; background:var(--wr-bg); padding:100px 32px 80px; overflow:hidden; } @media(max-width:768px){.hero{padding:60px 20px 60px}} /* Décor : 2 blobs très flous violet pâle, plus discrets */ .hero::before{ content:"";position:absolute; top:-260px;right:-180px;width:560px;height:560px; background:radial-gradient(circle,rgba(138,99,192,.14) 0%,transparent 65%); pointer-events:none;filter:blur(50px); } .hero::after{ content:"";position:absolute; bottom:-200px;left:-180px;width:480px;height:480px; background:radial-gradient(circle,rgba(138,99,192,.09) 0%,transparent 65%); pointer-events:none;filter:blur(50px); } .hero-dots{ position:absolute;inset:0; background-image:radial-gradient(circle,rgba(138,99,192,.07) 1px,transparent 1px); background-size:32px 32px; mask-image:radial-gradient(ellipse 60% 45% at 50% 45%,black,transparent 80%); -webkit-mask-image:radial-gradient(ellipse 60% 45% at 50% 45%,black,transparent 80%); pointer-events:none; } .hero-inner{position:relative;z-index:2;max-width:1100px;margin:0 auto;text-align:center} .hero-badge{ display:inline-flex;align-items:center;gap:8px; padding:7px 14px;border-radius:100px; background:var(--wr-card); border:1px solid var(--wr-line-2); color:var(--wr-violet-dark); font-size:12px;font-weight:500; margin-bottom:28px; box-shadow:var(--wr-shadow); opacity:0;transform:translateY(8px); animation:wrFadeUp .8s ease forwards; } .hero-badge-dot{width:6px;height:6px;border-radius:50%;background:#10B981;box-shadow:0 0 0 0 rgba(16,185,129,.4);animation:wrPulse2 2s ease infinite} @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)}} @keyframes wrFadeUp{to{opacity:1;transform:translateY(0)}} /* ═══ Titre hero — THIN large ═══ */ .hero-title{ font-weight:400; font-size:44px;line-height:1.04;letter-spacing:-0.04em; color:var(--wr-ink); margin:0 auto 24px; max-width:1000px; } @media(min-width:768px){.hero-title{font-size:68px;letter-spacing:-0.045em}} @media(min-width:1100px){.hero-title{font-size:88px}} .hero-title-line{display:block;opacity:0;transform:translateY(12px);animation:wrFadeUp .9s cubic-bezier(.2,.7,.2,1) forwards} .hero-title-line:nth-child(1){animation-delay:.1s} .hero-title-line:nth-child(2){animation-delay:.25s} .hero-title-line:nth-child(3){animation-delay:.4s} .hero-title-accent{ color:var(--wr-violet); font-weight:500; position:relative;display:inline-block; } .hero-title-accent::after{ content:""; position:absolute;left:0;right:0;bottom:.04em; height:.1em; background:var(--wr-violet); opacity:.22; transform-origin:left center; transform:scaleX(0); animation:wrUnderline 1.1s cubic-bezier(.6,0,.4,1) 1s forwards; border-radius:2px; } @keyframes wrUnderline{to{transform:scaleX(1)}} .hero-lede{ font-size:17px;line-height:1.55;color:var(--wr-ink-2);font-weight:400; margin:0 auto 36px;max-width:620px; opacity:0;animation:wrFadeUp .9s ease 1.1s forwards; } @media(min-width:768px){.hero-lede{font-size:18px}} /* ═══════════════════════════════════════════════════════════════════ HERO — RECHERCHE INLINE (avec résultats AJAX) ═══════════════════════════════════════════════════════════════════ */ .hero-search-wrap{ max-width:680px;margin:0 auto 28px; opacity:0;animation:wrFadeUp .9s ease 1.3s forwards; } .hero-search{ display:flex;align-items:center; background:var(--wr-card); border:1px solid var(--wr-line-2); border-radius:16px; padding:6px; box-shadow:0 2px 6px rgba(30,27,46,.04),0 16px 40px rgba(138,99,192,.08); transition:transform .2s,box-shadow .2s,border-color .2s,border-radius .25s; position:relative;z-index:5; } .hero-search:focus-within, .hero-search.has-results{ border-color:var(--wr-violet-2); box-shadow:0 4px 10px rgba(30,27,46,.05),0 20px 50px rgba(138,99,192,.16); } .hero-search.has-results{ border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-color:var(--wr-line); } .hero-search-icon{ display:flex;align-items:center;justify-content:center; width:42px;height:42px;flex-shrink:0;color:var(--wr-muted-2); } .hero-search-icon svg{width:18px;height:18px} .hero-search-input{ flex:1;border:0;outline:0;background:transparent; font-size:15px;font-family:inherit;color:var(--wr-ink); padding:0 6px;height:42px;min-width:0; } .hero-search-input::placeholder{color:var(--wr-muted-2)} .hero-search-clear{ display:none;align-items:center;justify-content:center; width:32px;height:32px;flex-shrink:0;color:var(--wr-muted-2); border:0;background:transparent;cursor:pointer;border-radius:8px; transition:background .15s,color .15s; } .hero-search-clear:hover{background:var(--wr-violet-soft);color:var(--wr-violet)} .hero-search-clear svg{width:14px;height:14px} .hero-search-clear.is-visible{display:inline-flex} .hero-search-btn{ background:var(--wr-violet);color:#fff; border:0;padding:0 22px;border-radius:11px; font-size:14px;font-weight:600;font-family:inherit; cursor:pointer;flex-shrink:0;height:42px; display:inline-flex;align-items:center;gap:6px; transition:background .15s,transform .15s,box-shadow .15s; box-shadow:0 4px 12px rgba(138,99,192,.3); } .hero-search-btn:hover{background:var(--wr-violet-dark);transform:translateY(-1px);box-shadow:0 6px 18px rgba(138,99,192,.4)} .hero-search-btn svg{width:13px;height:13px} @media(max-width:540px){.hero-search-btn span{display:none}.hero-search-btn{padding:0 14px}} /* Résultats inline */ .hero-search-results{ background:var(--wr-card); border:1px solid var(--wr-line); border-top:0; border-radius:0 0 16px 16px; max-height:0; overflow:hidden; transition:max-height .35s ease,padding .25s ease; text-align:left; box-shadow:0 16px 40px rgba(138,99,192,.1); padding:0 14px; } .hero-search-results.is-visible{max-height:560px;overflow-y:auto;padding:8px 14px 12px} .hero-search-results::-webkit-scrollbar{width:6px} .hero-search-results::-webkit-scrollbar-thumb{background:var(--wr-line-2);border-radius:6px} .hero-search-meta{ display:flex;align-items:center;justify-content:space-between;gap:10px; padding:10px 4px; font-size:11.5px;color:var(--wr-muted); text-transform:uppercase;letter-spacing:.08em;font-weight:600; } .hero-search-meta strong{color:var(--wr-violet);font-weight:700;font-size:13px} .hero-search-meta a{color:var(--wr-violet);font-weight:700;display:inline-flex;align-items:center;gap:4px} .hero-search-meta a svg{width:11px;height:11px} .hero-search-result{ display:flex;align-items:center;gap:12px; padding:10px 8px;border-radius:11px; text-decoration:none;color:inherit; transition:background .15s; } .hero-search-result:hover{background:var(--wr-violet-softer);text-decoration:none;color:inherit} .hero-search-result-logo{ width:38px;height:38px;border-radius:10px;flex-shrink:0; background:var(--wr-violet-soft);color:var(--wr-violet); display:flex;align-items:center;justify-content:center; font-weight:700;font-size:13px;overflow:hidden; } .hero-search-result-logo img{width:100%;height:100%;object-fit:cover} .hero-search-result-info{flex:1;min-width:0} .hero-search-result-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; } .hero-search-result-meta{ font-size:11.5px;color:var(--wr-muted);margin:0; white-space:nowrap;overflow:hidden;text-overflow:ellipsis; } .hero-search-result-cta{ font-size:11px;font-weight:600;color:var(--wr-violet); text-transform:uppercase;letter-spacing:.06em; display:inline-flex;align-items:center;gap:4px;flex-shrink:0; opacity:0;transition:opacity .15s,transform .15s;transform:translateX(-4px); } .hero-search-result:hover .hero-search-result-cta{opacity:1;transform:translateX(0)} .hero-search-result-cta svg{width:11px;height:11px} .hero-search-empty{ text-align:center;padding:36px 20px;color:var(--wr-muted); } .hero-search-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; } .hero-search-empty-icon svg{width:22px;height:22px} .hero-search-empty-title{font-weight:600;font-size:14px;color:var(--wr-ink);margin:0 0 4px} .hero-search-empty-hint{font-size:13px;margin:0;color:var(--wr-muted)} .hero-search-loading{ text-align:center;padding:30px 20px;color:var(--wr-muted);font-size:13px; display:flex;align-items:center;justify-content:center;gap:10px; } .hero-search-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; } @keyframes wrSpin{to{transform:rotate(360deg)}} /* Byline */ .hero-byline{ display:flex;align-items:center;justify-content:center;gap:20px;flex-wrap:wrap; font-size:13px;color:var(--wr-muted); opacity:0;animation:wrFadeUp .9s ease 1.5s forwards; } .hero-byline strong{color:var(--wr-violet);font-weight:700;font-size:15px;margin-right:3px} .hero-byline-sep{color:var(--wr-line-2)} .hero-byline svg{width:14px;height:14px;color:#10B981;flex-shrink:0} .hero-byline span{display:inline-flex;align-items:center;gap:6px} @media(max-width:540px){.hero-byline{gap:10px;font-size:12px}.hero-byline-sep{display:none}} /* ═══════════════════════════════════════════════════════════════════ SECTION : 3 PARCOURS ═══════════════════════════════════════════════════════════════════ */ .paths-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px} @media(max-width:991px){.paths-grid{grid-template-columns:1fr;gap:14px}} .path-card{ position:relative; background:var(--wr-card); border:1px solid var(--wr-line); border-radius:20px;padding:28px; display:flex;flex-direction:column; transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease; box-shadow:var(--wr-shadow); } .path-card:hover{transform:translateY(-4px);box-shadow:var(--wr-shadow-hover);border-color:var(--wr-violet-2)} .path-card-illu{ width:64px;height:64px;border-radius:16px; background:var(--wr-violet-soft);color:var(--wr-violet); display:flex;align-items:center;justify-content:center; margin-bottom:22px; } .path-card-illu svg{width:30px;height:30px} .path-card-label{ display:inline-block; font-size:11px;font-weight:600; color:var(--wr-violet-dark);text-transform:uppercase;letter-spacing:.1em; margin-bottom:10px;align-self:flex-start; } .path-card-title{ font-weight:500;font-size:22px;line-height:1.25;letter-spacing:-0.015em; color:var(--wr-ink);margin:0 0 10px; } .path-card-desc{ font-size:14px;line-height:1.6;color:var(--wr-muted); margin:0 0 22px;flex:1; } .path-card-cta{ display:inline-flex;align-items:center;justify-content:center;gap:6px; background:var(--wr-violet);color:#fff; padding:12px 18px;border-radius:11px; font-size:13px;font-weight:600; align-self:stretch; transition:background .15s,transform .15s,box-shadow .15s; box-shadow:0 2px 8px rgba(138,99,192,.2); } .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)} .path-card-cta svg{width:13px;height:13px;transition:transform .15s} .path-card-cta:hover svg{transform:translateX(3px)} /* ═══════════════════════════════════════════════════════════════════ MÉTHODE ═══════════════════════════════════════════════════════════════════ */ .method-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px} @media(max-width:991px){.method-grid{grid-template-columns:repeat(2,1fr)}} @media(max-width:540px){.method-grid{grid-template-columns:1fr}} .method-step{ background:var(--wr-card); border:1px solid var(--wr-line); border-radius:18px;padding:24px; transition:transform .2s,box-shadow .2s,border-color .2s; } .method-step:hover{transform:translateY(-3px);box-shadow:var(--wr-shadow-hover);border-color:var(--wr-violet-soft)} .method-num{ display:inline-flex;align-items:center;justify-content:center; width:36px;height:36px;border-radius:10px; background:var(--wr-violet-soft);color:var(--wr-violet); font-weight:700;font-size:14px;margin-bottom:16px; } .method-title{ font-weight:500;font-size:17px;line-height:1.25;letter-spacing:-0.005em; color:var(--wr-ink);margin:0 0 6px; } .method-desc{font-size:13px;line-height:1.55;color:var(--wr-muted);margin:0} /* ═══════════════════════════════════════════════════════════════════ MATCH ═══════════════════════════════════════════════════════════════════ */ .match-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:60px;align-items:center} @media(max-width:991px){.match-grid{grid-template-columns:1fr;gap:40px}} .match-text .wr-title{margin-left:0;text-align:left} .match-text .wr-lede{margin-left:0;text-align:left} .match-text .wr-eyebrow{margin-bottom:20px} .match-features{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:32px} @media(max-width:540px){.match-features{grid-template-columns:1fr}} .match-feature{ background:var(--wr-card);border:1px solid var(--wr-line); border-radius:14px;padding:18px; transition:transform .15s,border-color .15s,box-shadow .15s; } .match-feature:hover{transform:translateY(-2px);border-color:var(--wr-violet-soft);box-shadow:var(--wr-shadow)} .match-feature-icon{ width:34px;height:34px;border-radius:10px; background:var(--wr-violet-soft);color:var(--wr-violet); display:inline-flex;align-items:center;justify-content:center;margin-bottom:12px; } .match-feature-icon svg{width:16px;height:16px} .match-feature-title{font-weight:600;font-size:14px;line-height:1.3;color:var(--wr-ink);margin:0 0 5px} .match-feature-desc{font-size:12.5px;line-height:1.5;color:var(--wr-muted);margin:0} .match-visual{position:relative;display:flex;justify-content:center;align-items:center;padding:40px 0} .match-stack{position:relative;width:100%;max-width:340px;height:340px} .match-stack-card{ position:absolute; background:var(--wr-card);border:1px solid var(--wr-line); border-radius:16px;padding:14px; display:flex;align-items:center;gap:12px; box-shadow:var(--wr-shadow);width:100%; transition:transform .3s ease; } .match-stack-card:nth-child(1){top:0;transform:rotate(-6deg) translateX(-10px);z-index:1;animation:wrFloat 6s ease-in-out infinite} .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:wrFloat 6s ease-in-out -2s infinite} .match-stack-card:nth-child(3){top:156px;transform:rotate(-3deg) translateX(8px);z-index:2;animation:wrFloat 6s ease-in-out -4s infinite} .match-stack-card:nth-child(4){top:234px;left:20px;transform:rotate(4deg);z-index:1;animation:wrFloat 6s ease-in-out -1s infinite} @keyframes wrFloat{0%,100%{transform:translateY(0) rotate(var(--r,0))}50%{transform:translateY(-6px) rotate(var(--r,0))}} .match-stack-logo{ width:38px;height:38px;border-radius:10px; background:var(--wr-violet-soft);color:var(--wr-violet); display:flex;align-items:center;justify-content:center; font-weight:700;font-size:14px;flex-shrink:0; } .match-stack-info{flex:1;min-width:0} .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} .match-stack-meta{font-size:11px;color:var(--wr-muted);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} .match-stack-heart{width:28px;height:28px;border-radius:50%;background:#FEE2E2;color:#EF4444;display:flex;align-items:center;justify-content:center;flex-shrink:0} .match-stack-heart svg{width:13px;height:13px;fill:currentColor} /* ═══════════════════════════════════════════════════════════════════ APPS ═══════════════════════════════════════════════════════════════════ */ .apps-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px} @media(max-width:768px){.apps-grid{grid-template-columns:1fr}} .app-card{ background:var(--wr-card);border:1px solid var(--wr-line); border-radius:18px;padding:24px; display:flex;flex-direction:column;align-items:flex-start; transition:transform .2s,border-color .2s,box-shadow .2s; } .app-card:hover{transform:translateY(-3px);border-color:var(--wr-violet-2);box-shadow:var(--wr-shadow-hover);color:inherit;text-decoration:none} .app-card-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:18px; } .app-card-icon svg{width:22px;height:22px} .app-card-name{font-weight:500;font-size:18px;letter-spacing:-0.01em;color:var(--wr-ink);margin:0 0 6px} .app-card-desc{font-size:13px;line-height:1.5;color:var(--wr-muted);margin:0 0 16px;flex:1} .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} .app-card-cta svg{width:11px;height:11px;transition:transform .15s} .app-card:hover .app-card-cta svg{transform:translateX(3px)} /* ═══════════════════════════════════════════════════════════════════ KEYWORDS ═══════════════════════════════════════════════════════════════════ */ .keywords-list{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;max-width:920px;margin:0 auto} .keyword-pill{ display:inline-flex;align-items:center;gap:8px; padding:9px 16px;border-radius:100px; background:var(--wr-card);border:1px solid var(--wr-line-2); color:var(--wr-ink-2); font-size:13.5px;font-weight:500; transition:transform .15s,border-color .15s,background .15s,color .15s,box-shadow .15s; } .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)} .keyword-pill-icon{font-size:14px;line-height:1} /* ═══════════════════════════════════════════════════════════════════ OFFRES POPULAIRES ═══════════════════════════════════════════════════════════════════ */ .listings-block{margin-bottom:32px} .listings-block:last-child{margin-bottom:0} .listings-block-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:14px;flex-wrap:wrap} .listings-block-title{ display:inline-flex;align-items:center;gap:10px; font-weight:500;font-size:18px;letter-spacing:-0.005em; color:var(--wr-ink);margin:0; } .listings-block-icon{font-size:20px;line-height:1} .listings-block-link{ display:inline-flex;align-items:center;gap:4px; padding:6px 12px;border-radius:100px; font-size:12px;font-weight:600; color:var(--wr-violet); text-transform:uppercase;letter-spacing:.06em; border:1px solid var(--wr-violet-soft); background:var(--wr-card); transition:background .15s,border-color .15s,transform .15s; } .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)} .listings-block-link svg{width:11px;height:11px} .listings-jobs{display:grid;grid-template-columns:1fr 1fr;gap:10px} @media(max-width:768px){.listings-jobs{grid-template-columns:1fr}} .listing-job{ display:flex;align-items:center;gap:14px; background:var(--wr-card);border:1px solid var(--wr-line); border-radius:14px;padding:12px; transition:transform .15s,border-color .15s,box-shadow .15s; } .listing-job:hover{transform:translateY(-2px);border-color:var(--wr-violet-soft);box-shadow:var(--wr-shadow);color:inherit;text-decoration:none} .listing-job-logo{ width:42px;height:42px;border-radius:11px;flex-shrink:0; background:var(--wr-violet-soft);color:var(--wr-violet); display:flex;align-items:center;justify-content:center; font-weight:700;font-size:14px;overflow:hidden; } .listing-job-logo img{width:100%;height:100%;object-fit:cover} .listing-job-info{flex:1;min-width:0} .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} .listing-job-meta{font-size:11.5px;color:var(--wr-muted);margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} .listing-job-arrow{flex-shrink:0;color:var(--wr-muted-2);transition:color .15s,transform .15s} .listing-job-arrow svg{width:14px;height:14px} .listing-job:hover .listing-job-arrow{color:var(--wr-violet);transform:translateX(2px)} /* ═══════════════════════════════════════════════════════════════════ ARTICLES ═══════════════════════════════════════════════════════════════════ */ .articles-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px} @media(max-width:991px){.articles-grid{grid-template-columns:repeat(2,1fr)}} @media(max-width:640px){.articles-grid{grid-template-columns:1fr}} .wr-article{ background:var(--wr-card);border:1px solid var(--wr-line); border-radius:18px;overflow:hidden; display:flex;flex-direction:column; transition:transform .2s,box-shadow .2s,border-color .2s; } .wr-article:hover{transform:translateY(-3px);box-shadow:var(--wr-shadow-hover);border-color:var(--wr-violet-2);color:inherit;text-decoration:none} .wr-article-img{aspect-ratio:16/10;background:var(--wr-violet-soft);overflow:hidden;flex-shrink:0} .wr-article-img img{width:100%;height:100%;object-fit:cover;transition:transform .4s ease} .wr-article:hover .wr-article-img img{transform:scale(1.04)} .wr-article-body{padding:18px;flex:1;display:flex;flex-direction:column} .wr-article-meta{font-size:11px;font-weight:600;color:var(--wr-violet-dark);text-transform:uppercase;letter-spacing:.08em;margin:0 0 8px} .wr-article-title{font-weight:500;font-size:16px;line-height:1.35;letter-spacing:-0.005em;color:var(--wr-ink);margin:0 0 8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden} .wr-article-excerpt{font-size:13px;line-height:1.5;color:var(--wr-muted);margin:0 0 14px;flex:1;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden} .wr-article-link{font-size:12px;font-weight:600;color:var(--wr-violet);text-transform:uppercase;letter-spacing:.06em;display:inline-flex;align-items:center;gap:4px} .wr-article-link svg{width:11px;height:11px;transition:transform .15s} .wr-article:hover .wr-article-link svg{transform:translateX(3px)} .articles-cta{text-align:center;margin-top:36px} .articles-cta a{ display:inline-flex;align-items:center;gap:8px; padding:12px 22px;border-radius:11px; background:var(--wr-card);border:1px solid var(--wr-line-2); color:var(--wr-violet); font-size:13px;font-weight:600; transition:background .15s,transform .15s,border-color .15s; } .articles-cta a:hover{background:var(--wr-violet-soft);border-color:var(--wr-violet);transform:translateY(-2px);text-decoration:none;color:var(--wr-violet-dark)} .articles-cta svg{width:12px;height:12px} /* ═══════════════════════════════════════════════════════════════════ CTA FINAL ═══════════════════════════════════════════════════════════════════ */ .final-card{ position:relative; background:linear-gradient(135deg,var(--wr-violet) 0%,var(--wr-violet-dark) 100%); border-radius:28px; padding:64px 32px;text-align:center; color:#fff;overflow:hidden; box-shadow:0 20px 60px -12px rgba(138,99,192,.4); } @media(max-width:768px){.final-card{padding:48px 24px;border-radius:22px}} .final-card::before{content:"";position:absolute;top:-100px;right:-100px;width:300px;height:300px;background:radial-gradient(circle,rgba(255,255,255,.18) 0%,transparent 65%);pointer-events:none} .final-card::after{content:"";position:absolute;bottom:-120px;left:-100px;width:280px;height:280px;background:radial-gradient(circle,rgba(255,255,255,.12) 0%,transparent 65%);pointer-events:none} .final-title{font-weight:500;font-size:32px;line-height:1.1;letter-spacing:-0.025em;color:#fff;margin:0 0 14px;position:relative;z-index:2} @media(min-width:768px){.final-title{font-size:44px}} .final-subtitle{font-size:16px;line-height:1.55;color:rgba(255,255,255,.88);margin:0 auto 32px;max-width:520px;position:relative;z-index:2} .final-buttons{display:flex;justify-content:center;gap:12px;flex-wrap:wrap;position:relative;z-index:2} .final-btn{ display:inline-flex;align-items:center;gap:8px; padding:14px 24px;border-radius:12px; font-size:14px;font-weight:600; transition:transform .15s,background .15s,box-shadow .15s; } .final-btn--primary{background:#fff;color:var(--wr-violet-dark)} .final-btn--primary:hover{transform:translateY(-2px);box-shadow:0 12px 28px rgba(0,0,0,.15);color:var(--wr-violet-dark);text-decoration:none} .final-btn--ghost{background:rgba(255,255,255,.12);color:#fff;border:1px solid rgba(255,255,255,.25);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)} .final-btn--ghost:hover{background:rgba(255,255,255,.2);transform:translateY(-2px);color:#fff;text-decoration:none} .final-btn svg{width:14px;height:14px;transition:transform .15s} .final-btn:hover svg{transform:translateX(3px)} </style>{% endblock css %}{% block body %} <div class="wr"> {# ═══════════════ HERO ═══════════════ #} <section class="hero"> <span class="hero-dots"></span> <div class="hero-inner"> <span class="hero-badge"> <span class="hero-badge-dot"></span> {{ t.hero_eyebrow }} </span> <h1 class="hero-title"> <span class="hero-title-line">{{ t.hero_title_1 }}</span> <span class="hero-title-line"><span class="hero-title-accent">{{ t.hero_title_2 }}</span></span> <span class="hero-title-line">{{ t.hero_title_3 }}</span> </h1> <p class="hero-lede">{{ t.hero_lede }}</p> {# Recherche inline AJAX #} <div class="hero-search-wrap"> <form class="hero-search" id="wrHeroSearch" autocomplete="off" data-search-url="{% if isFR %}{{ path('locale_api_jobs_search',{'_locale':'fr'}) }}{% else %}{{ path('api_jobs_search') }}{% endif %}" data-jobs-list-url="{% if isFR %}{{ path('locale_whileresume_jobs_list',{'_locale':'fr'}) }}{% else %}{{ path('whileresume_jobs_list') }}{% endif %}"> <span class="hero-search-icon"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/> </svg> </span> <input type="text" name="q" id="wrHeroSearchInput" class="hero-search-input" placeholder="{{ t.hero_search_placeholder }}" /> <button type="button" class="hero-search-clear" id="wrHeroSearchClear" aria-label="{{ t.search_clear }}"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/> </svg> </button> <button type="submit" class="hero-search-btn"> <span>{{ t.hero_search_button }}</span> <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> </button> </form> {# Container des résultats inline #} <div class="hero-search-results" id="wrHeroSearchResults" aria-live="polite"></div> </div> <div class="hero-byline"> <span><strong>{{ totalJobs ?? '—' }}</strong> {{ t.hero_byline_jobs }}</span> <span class="hero-byline-sep">·</span> <span>{{ t.hero_byline_apps }}</span> <span class="hero-byline-sep">·</span> <span> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg> {{ t.hero_byline_free }} </span> </div> </div> </section> {# ═══════════════ 3 PARCOURS ═══════════════ #} <section class="wr-section"> <div class="wr-container"> <div class="wr-section-head"> <span class="wr-eyebrow">{{ t.paths_eyebrow }}</span> <h2 class="wr-title">{{ t.paths_title }}</h2> <p class="wr-lede">{{ t.paths_lede }}</p> </div> <div class="paths-grid"> <article class="path-card"> <div class="path-card-illu"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/> <line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/> </svg> </div> <span class="path-card-label">{{ t.path1_label }}</span> <h3 class="path-card-title">{{ t.path1_title }}</h3> <p class="path-card-desc">{{ t.path1_desc }}</p> <a href="{{ path('whileresume_resume_' ~ app.request.locale) }}" class="path-card-cta"> {{ t.path1_cta }} <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> </a> </article> <article class="path-card"> <div class="path-card-illu"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"> <path d="M9 11H5a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2h-4"/> <polyline points="9 7 12 4 15 7"/><line x1="12" y1="4" x2="12" y2="14"/> </svg> </div> <span class="path-card-label">{{ t.path2_label }}</span> <h3 class="path-card-title">{{ t.path2_title }}</h3> <p class="path-card-desc">{{ t.path2_desc }}</p> <a href="{{ path('whileresume_resume_' ~ app.request.locale) }}" class="path-card-cta"> {{ t.path2_cta }} <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> </a> </article> <article class="path-card"> <div class="path-card-illu"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"> <rect x="2" y="6" width="20" height="14" rx="2"/> <path d="M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/> <line x1="2" y1="13" x2="22" y2="13"/> </svg> </div> <span class="path-card-label">{{ t.path3_label }}</span> <h3 class="path-card-title">{{ t.path3_title }}</h3> <p class="path-card-desc">{{ t.path3_desc }}</p> <a href="{% if isFR %}{{ path('locale_whileresume_jobs_list',{'_locale':'fr'}) }}{% else %}{{ path('whileresume_jobs_list') }}{% endif %}" class="path-card-cta"> {{ t.path3_cta }} <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> </a> </article> </div> </div> </section> {# ═══════════════ MÉTHODE ═══════════════ #} <section class="wr-section"> <div class="wr-container"> <div class="wr-section-head"> <span class="wr-eyebrow">{{ t.how_eyebrow }}</span> <h2 class="wr-title">{{ t.how_title }}</h2> <p class="wr-lede">{{ t.how_lede }}</p> </div> <div class="method-grid"> <div class="method-step"> <div class="method-num">01</div> <h3 class="method-title">{{ t.step1_title }}</h3> <p class="method-desc">{{ t.step1_desc }}</p> </div> <div class="method-step"> <div class="method-num">02</div> <h3 class="method-title">{{ t.step2_title }}</h3> <p class="method-desc">{{ t.step2_desc }}</p> </div> <div class="method-step"> <div class="method-num">03</div> <h3 class="method-title">{{ t.step3_title }}</h3> <p class="method-desc">{{ t.step3_desc }}</p> </div> <div class="method-step"> <div class="method-num">04</div> <h3 class="method-title">{{ t.step4_title }}</h3> <p class="method-desc">{{ t.step4_desc }}</p> </div> </div> </div> </section> {# ═══════════════ MATCH ═══════════════ #} <section class="wr-section"> <div class="wr-container"> <div class="match-grid"> <div class="match-text"> <span class="wr-eyebrow">{{ t.match_eyebrow }}</span> <h2 class="wr-title wr-title--sm">{{ t.match_title }}</h2> <p class="wr-lede">{{ t.match_lede }}</p> <div class="match-features"> <div class="match-feature"> <div class="match-feature-icon"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg> </div> <h4 class="match-feature-title">{{ t.match_b1_title }}</h4> <p class="match-feature-desc">{{ t.match_b1_desc }}</p> </div> <div class="match-feature"> <div class="match-feature-icon"> <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"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg> </div> <h4 class="match-feature-title">{{ t.match_b2_title }}</h4> <p class="match-feature-desc">{{ t.match_b2_desc }}</p> </div> <div class="match-feature"> <div class="match-feature-icon"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> </div> <h4 class="match-feature-title">{{ t.match_b3_title }}</h4> <p class="match-feature-desc">{{ t.match_b3_desc }}</p> </div> <div class="match-feature"> <div class="match-feature-icon"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> </div> <h4 class="match-feature-title">{{ t.match_b4_title }}</h4> <p class="match-feature-desc">{{ t.match_b4_desc }}</p> </div> </div> </div> <div class="match-visual"> <div class="match-stack"> <div class="match-stack-card"> <div class="match-stack-logo">A</div> <div class="match-stack-info"> <p class="match-stack-title">Lead Designer</p> <p class="match-stack-meta">Acme · Remote</p> </div> <div class="match-stack-heart"><svg viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg></div> </div> <div class="match-stack-card"> <div class="match-stack-logo">N</div> <div class="match-stack-info"> <p class="match-stack-title">Frontend Engineer</p> <p class="match-stack-meta">Notion · Paris</p> </div> <div class="match-stack-heart"><svg viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg></div> </div> <div class="match-stack-card"> <div class="match-stack-logo">L</div> <div class="match-stack-info"> <p class="match-stack-title">Product Manager</p> <p class="match-stack-meta">Linear · {{ isFR ? 'Hybride' : 'Hybrid' }}</p> </div> <div class="match-stack-heart"><svg viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg></div> </div> <div class="match-stack-card"> <div class="match-stack-logo">F</div> <div class="match-stack-info"> <p class="match-stack-title">Data Analyst</p> <p class="match-stack-meta">Figma · Lyon</p> </div> <div class="match-stack-heart"><svg viewBox="0 0 24 24"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg></div> </div> </div> </div> </div> </div> </section> {# ═══════════════ APPS ═══════════════ #} <section class="wr-section"> <div class="wr-container"> <div class="wr-section-head"> <span class="wr-eyebrow">{{ t.apps_eyebrow }}</span> <h2 class="wr-title wr-title--sm">{{ t.apps_title }}</h2> <p class="wr-lede">{{ t.apps_lede }}</p> </div> <div class="apps-grid"> <a href="#" class="app-card"> <span class="app-card-icon"> <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> </span> <h3 class="app-card-name">{{ t.apps_ios }}</h3> <p class="app-card-desc">{{ t.apps_ios_desc }}</p> <span class="app-card-cta">App Store <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> </span> </a> <a href="#" class="app-card"> <span class="app-card-icon"> <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> </span> <h3 class="app-card-name">{{ t.apps_android }}</h3> <p class="app-card-desc">{{ t.apps_android_desc }}</p> <span class="app-card-cta">Google Play <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> </span> </a> <a href="{{ path('whileresume_resume_' ~ app.request.locale) }}" class="app-card"> <span class="app-card-icon"> <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> </span> <h3 class="app-card-name">{{ t.apps_web }}</h3> <p class="app-card-desc">{{ t.apps_web_desc }}</p> <span class="app-card-cta">whileresume.com <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> </span> </a> </div> </div> </section> {# ═══════════════ KEYWORDS ═══════════════ #} {% if popularKeywords is defined and popularKeywords|length > 0 %} <section class="wr-section wr-section--tight"> <div class="wr-container"> <div class="wr-section-head"> <h2 class="wr-title wr-title--sm">{{ t.keywords_title }}</h2> <p class="wr-lede">{{ t.keywords_lede }}</p> </div> <div class="keywords-list"> {% for kw in popularKeywords %} <a href="{% if isFR %}{{ path('locale_whileresume_jobs_list',{'_locale':'fr'}) }}{% else %}{{ path('whileresume_jobs_list') }}{% endif %}?q={{ kw.keyword|url_encode }}" class="keyword-pill"> {% if kw.icon %}<span class="keyword-pill-icon">{{ kw.icon|raw }}</span>{% endif %} <span>{{ kw.label }}</span> </a> {% endfor %} </div> </div> </section> {% endif %} {# ═══════════════ OFFRES POPULAIRES ═══════════════ #} {% if popularJobs is defined and popularJobs|length > 0 %} <section class="wr-section"> <div class="wr-container"> <div class="wr-section-head"> <h2 class="wr-title wr-title--sm">{{ t.popular_title }}</h2> <p class="wr-lede">{{ t.popular_lede }}</p> </div> {% for block in popularJobs %} {% if block.jobs|length > 0 %} <div class="listings-block"> <div class="listings-block-head"> <h3 class="listings-block-title"> {% if block.icon %}<span class="listings-block-icon">{{ block.icon|raw }}</span>{% endif %} {{ block.label }} </h3> <a href="{% if isFR %}{{ path('locale_whileresume_jobs_list',{'_locale':'fr'}) }}{% else %}{{ path('whileresume_jobs_list') }}{% endif %}?q={{ block.label|url_encode }}" class="listings-block-link"> {{ t.btn_more }} <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> </a> </div> <div class="listings-jobs"> {% for j in block.jobs|slice(0, 4) %} <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="listing-job"> <div class="listing-job-logo"> {% if j.image and j.image.name %} <img src="{{ vich_uploader_asset(j, 'imageFile') }}" alt=""> {% else %} {{ j.companyName|default('?')|slice(0,1)|upper }} {% endif %} </div> <div class="listing-job-info"> <h4 class="listing-job-title">{{ j.jobTitle }}</h4> <p class="listing-job-meta"> {{ j.companyName }}{% if j.city %} · {{ j.city }}{% endif %}{% if j.employmentType %} · {{ j.employmentType }}{% endif %} </p> </div> <span class="listing-job-arrow"> <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> </span> </a> {% endfor %} </div> </div> {% endif %} {% endfor %} </div> </section> {% endif %} {# ═══════════════ ARTICLES ═══════════════ #} {% if articles is defined and articles|length > 0 %} <section class="wr-section"> <div class="wr-container"> <div class="wr-section-head"> <h2 class="wr-title wr-title--sm">{{ t.articles_title }}</h2> <p class="wr-lede">{{ t.articles_lede }}</p> </div> <div class="articles-grid"> {% for a in articles|slice(0,6) %} {% set prefix = "" %} {% set urlA = path('cvs_website_article',{'slug': a.slug}) %} {% if app.request.locale != default_locale %} {% set urlA = path('locale_cvs_website_article',{'_locale':app.request.locale,'slug': a.slug}) %} {% set prefix = "/" ~ app.request.locale %} {% endif %} {% if a.pageslug3 is not empty %} {% set urlA = prefix ~ '/' ~ a.pageslug ~ '/' ~ a.pageslug2 ~ '/' ~ a.pageslug3 %} {% elseif a.pageslug2 is not empty %} {% set urlA = prefix ~ '/' ~ a.pageslug ~ '/' ~ a.pageslug2 %} {% elseif a.pageslug is not empty %} {% set urlA = prefix ~ '/' ~ a.pageslug %} {% endif %} <a href="{{ urlA }}" class="wr-article"> <div class="wr-article-img"> {% if a.image.name is not null %} <img src="{{ vich_uploader_asset(a, 'imageFile') }}" alt="{{ a.title }}"> {% endif %} </div> <div class="wr-article-body"> <p class="wr-article-meta"> {{ a.publishedAt|date(isFR ? 'd M Y' : 'M d, Y') }}{% if a.author %} · {{ a.author }}{% endif %} </p> <h3 class="wr-article-title">{{ a.title }}</h3> {% if a.subtitle %}<p class="wr-article-excerpt">{{ a.subtitle }}</p>{% endif %} <span class="wr-article-link"> {{ t.read_article }} <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> </span> </div> </a> {% endfor %} </div> <div class="articles-cta"> <a href="{% if isFR %}{{ path('locale_cvs_website_articles',{'_locale':'fr'}) }}{% else %}{{ path('cvs_website_articles') }}{% endif %}"> {{ t.articles_view_all }} <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> </a> </div> </div> </section> {% endif %} {# ═══════════════ CTA FINAL ═══════════════ #} <section class="wr-section"> <div class="wr-container"> <div class="final-card"> <h2 class="final-title">{{ t.final_title }}</h2> <p class="final-subtitle">{{ t.final_subtitle }}</p> <div class="final-buttons"> <a href="{{ path('whileresume_resume_' ~ app.request.locale) }}" class="final-btn final-btn--primary"> {{ t.final_candidate }} <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> </a> <a href="{{ path('whileresume_business_' ~ app.request.locale) }}" class="final-btn final-btn--ghost"> {{ t.final_recruiter }} <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> </a> </div> </div> </div> </section> </div>{% endblock body %}{% block footer_js %} {{ parent() }} <script> (function(){ var form = document.getElementById('wrHeroSearch'); var input = document.getElementById('wrHeroSearchInput'); var clearBtn = document.getElementById('wrHeroSearchClear'); var results = document.getElementById('wrHeroSearchResults'); if (!form || !input || !results) return; var searchUrl = form.dataset.searchUrl; var jobsListUrl = form.dataset.jobsListUrl; var debounceTimer = null; var currentRequest = null; var lastQuery = ''; var T = { loading: '{{ t.search_loading|escape('js') }}', empty: '{{ t.search_no_results|escape('js') }}', emptyHint:'{{ t.search_no_results_hint|escape('js') }}', count: '{{ t.search_results_count|escape('js') }}', viewAll: '{{ t.search_view_all|escape('js') }}', view: '{{ t.search_view_offer|escape('js') }}' }; function escHtml(s){ if (s == null) return ''; return String(s).replace(/[&<>"']/g, function(c){ return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]; }); } function showResults(){ results.classList.add('is-visible'); form.classList.add('has-results'); } function hideResults(){ results.classList.remove('is-visible'); form.classList.remove('has-results'); } function setLoading(){ results.innerHTML = '<div class="hero-search-loading">' + '<span class="hero-search-spinner"></span>' + '<span>' + escHtml(T.loading) + '</span>' + '</div>'; showResults(); } function renderResults(payload, query){ var jobs = (payload && payload.jobs) || []; var total = (payload && typeof payload.total === 'number') ? payload.total : jobs.length; if (!jobs.length){ results.innerHTML = '<div class="hero-search-empty">' + '<div class="hero-search-empty-icon">' + '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">' + '<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>' + '</svg>' + '</div>' + '<p class="hero-search-empty-title">' + escHtml(T.empty) + '</p>' + '<p class="hero-search-empty-hint">' + escHtml(T.emptyHint) + '</p>' + '</div>'; showResults(); return; } var html = '<div class="hero-search-meta">' + '<span><strong>' + total + '</strong> ' + escHtml(T.count) + '</span>' + '<a href="' + jobsListUrl + '?q=' + encodeURIComponent(query) + '">' + escHtml(T.viewAll) + '<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>' + '</a>' + '</div>'; jobs.slice(0, 6).forEach(function(j){ var title = j.jobTitle || j.title || ''; var company = j.companyName || j.company || ''; var city = j.city || ''; var et = j.employmentType || ''; var slug = j.slug || ''; var img = j.image || j.imageUrl || ''; var url = j.url || (jobsListUrl + '?q=' + encodeURIComponent(query)); var initial = (company || title || '?').charAt(0).toUpperCase(); var meta = [company, city, et].filter(function(x){ return x; }).join(' · '); html += '<a href="' + escHtml(url) + '" class="hero-search-result">' + '<div class="hero-search-result-logo">' + (img ? '<img src="' + escHtml(img) + '" alt="">' : escHtml(initial)) + '</div>' + '<div class="hero-search-result-info">' + '<p class="hero-search-result-title">' + escHtml(title) + '</p>' + '<p class="hero-search-result-meta">' + escHtml(meta) + '</p>' + '</div>' + '<span class="hero-search-result-cta">' + escHtml(T.view) + '<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>' + '</span>' + '</a>'; }); results.innerHTML = html; showResults(); } function doSearch(query){ if (currentRequest && currentRequest.abort) { try { currentRequest.abort(); } catch(e){} } setLoading(); var url = searchUrl + (searchUrl.indexOf('?') > -1 ? '&' : '?') + 'q=' + encodeURIComponent(query); var ctrl = (typeof AbortController !== 'undefined') ? new AbortController() : null; currentRequest = ctrl; fetch(url, { headers: { 'Accept': 'application/json' }, signal: ctrl ? ctrl.signal : undefined }) .then(function(r){ return r.ok ? r.json() : Promise.reject(r.status); }) .then(function(data){ renderResults(data, query); }) .catch(function(err){ if (err && err.name === 'AbortError') return; results.innerHTML = '<div class="hero-search-empty">' + '<p class="hero-search-empty-title">' + escHtml(T.empty) + '</p>' + '<p class="hero-search-empty-hint">' + escHtml(T.emptyHint) + '</p>' + '</div>'; showResults(); }); } // Input live (debounce 280ms) input.addEventListener('input', function(){ var q = input.value.trim(); clearBtn.classList.toggle('is-visible', q.length > 0); if (debounceTimer) clearTimeout(debounceTimer); if (q.length < 2){ hideResults(); lastQuery = ''; return; } if (q === lastQuery) return; debounceTimer = setTimeout(function(){ lastQuery = q; doSearch(q); }, 280); }); // Submit → page de résultats complète form.addEventListener('submit', function(e){ var q = input.value.trim(); if (!q) { e.preventDefault(); return; } window.location.href = jobsListUrl + '?q=' + encodeURIComponent(q); e.preventDefault(); }); // Clear clearBtn.addEventListener('click', function(){ input.value = ''; clearBtn.classList.remove('is-visible'); hideResults(); lastQuery = ''; input.focus(); }); // Escape ferme input.addEventListener('keydown', function(e){ if (e.key === 'Escape'){ hideResults(); input.blur(); } }); // Clic en dehors ferme (mais pas si on clique dedans) document.addEventListener('click', function(e){ if (!form.contains(e.target) && !results.contains(e.target)){ hideResults(); } }); // Refocus input → ré-affiche les derniers résultats si on en avait input.addEventListener('focus', function(){ if (input.value.trim().length >= 2 && results.innerHTML.trim()) showResults(); }); })(); </script>{% endblock footer_js %}