1<!DOCTYPE html><html lang="fr"><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><title data-next-head="">Ask Combak â Trouve ton bonheur</title><meta name="robots" content="noindex, nofollow" data-next-head=""/><meta name="viewport" content="width=device-width, initial-scale=1"/><meta name="p:domain_verify" content="b973e190377c1f96e6542bc642322eee"/><link rel="alternate" type="application/rss+xml" title="Combak Blog RSS Feed" href="/api/rss"/><style>/* antd brand colors â inlined to win against antd CSS-in-JS defaults 2injected at SSR. Without this, sliders render in #1677ff blue and checkboxes 3have #d9d9d9 grey borders (antd defaults) at first paint, then flip to brand 4green after hydration. Cause: the antd theme tokens (themeConfig.ts) are not 5captured by extractStyle() reliably for some components in dev OR prod. */ 6.ant-slider .ant-slider-track{background-color:#02422a!important} 7.ant-slider .ant-slider-handle::after{background-color:#bef06d!important;border-radius:50px!important} 8.ant-slider .ant-slider-rail{background-color:rgba(0,0,0,0.06)!important} 9.ant-checkbox .ant-checkbox-inner{border-color:#02422a!important} 10.ant-checkbox-checked .ant-checkbox-inner{background-color:#bef06d!important;border-color:#02422a!important} 11.ant-checkbox-checked .ant-checkbox-inner::after{border-color:#02422a!important} 12.ant-checkbox-wrapper:hover .ant-checkbox-inner,.ant-checkbox:hover .ant-checkbox-inner{border-color:#02422a!important} 13.ant-checkbox-wrapper-checked:hover .ant-checkbox-inner,.ant-checkbox-checked:hover .ant-checkbox-inner{background-color:#bef06d!important;border-color:#02422a!important} 14/* Breadcrumb tailles inline pour éviter le shrink "gros â normal" sur mobile. 15 En dev mode, le CSS module Breadcrumb.module.scss n'est pas chargé synchrone 16 â la règle media @max-width 767px {font-size:13px} arrive après hydratation 17 â le breadcrumb apparait gros (16px) puis shrink. Ces règles couvrent les 18 2 breakpoints sans dépendre du CSS module. */ 19.ant-breadcrumb{font-size:16px;line-height:24px;color:var(--text-secondary)} 20.ant-breadcrumb a{color:var(--text-primary);font-weight:500} 21@media(max-width:767px){.ant-breadcrumb{font-size:13px;line-height:20px}} 22:root{--almost-black:#20201e;--seasalt:#f7f7f7;--lime:#bef06d;--dark-green:#02422a;--white-100:#fff;--black-100:#e6e6e5;--black-300:#b7b7b3;--black-400:#9f9f98;--black-700:#54544f;--black-900:#20201e;--lime-500:#bef06d;--green-800:#02422a;--surface-primary:var(--seasalt);--surface-secondary:var(--white-100);--text-primary:var(--black-900);--text-secondary:var(--black-700);--text-tertiary:var(--black-400);--text-brand:var(--green-800);--padding-lg:8px;--padding-xl:12px;--padding-2xl:16px;--padding-3xl:24px;--horizontal-spacing-lg:16px;
22--horizontal-spacing-2xl:40px;--horizontal-spacing-4xl:64px;--vertical-spacing-4xl:40px;--vertical-spacing-6xl:80px;--radius-2xl:16px;--radius-3xl:24px;--shadow-sm:1px 1px 16px hsla(60,3%,12%,.08);--text-body-md:16px;--text-body-sm:14px;--text-heading-1:36px;--text-heading-2:32px}*{box-sizing:border-box;padding:0;margin:0}html,body{width:100%;height:100vh;font-family:"Manrope",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Helvetica Neue",Arial,sans-serif;font-weight:400;line-height:1.4;font-synthesis-weight:none;font-synthesis-style:none}body{color:var(--text-primary);position:relative;background-color:var(--surface-primary)}main{min-height:calc(100vh - 110px)}@media (min-width:1000px){main{min-height:calc(100vh - 90px)}}a{color:inherit;font-weight:500;text-decoration:none}h1,h2,h3,h4,h5,h6{color:var(--text-brand);margin-bottom:0;font-weight:700;font-family:"Rubik",sans-serif;text-transform:uppercase}header{z-index:999;position:sticky;top:0;left:0;right:0;background-color:#fff}header .Logo{width:150px;height:100%;padding:0;margin:0}@media (min-width:1000px){header .DesktopWrapper{display:block}header .MobileWrapper{display:none}header .Row{height:80px;display:flex;align-items:center;justify-content:space-between;gap:var(--vertical-spacing-4xl)}}@media (max-width:999px){header .DesktopWrapper{display:none}header .MobileWrapper{display:block}}.container{width:100%;max-width:1440px;margin:0 auto;padding:0 var(--padding-2xl)}@media (min-width:768px){.container{padding:0 var(--padding-3xl)}}article{position:relative;padding:var(--padding-2xl) var(--padding-xl) var(--padding-lg) var(--padding-xl);display:flex;flex-direction:column;gap:var(--horizontal-spacing-lg);
22min-width:200px;border-radius:var(--radius-2xl);background-color:var(--surface-secondary);box-shadow:var(--shadow-sm)}figure{margin:0;position:relative;aspect-ratio:1/1;overflow:hidden;border-radius:8px;max-height:135px}.products-grid{display:grid;gap:var(--horizontal-spacing-2xl);grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}.body-md{font-size:var(--text-body-md)}.body-sm{font-size:var(--text-body-sm)}.w-700{font-weight:700}.w-500{font-weight:500}.overline{font-size:12px;font-weight:500;text-transform:uppercase;letter-spacing:.5px}.color-tertiary{color:var(--text-tertiary)}.ant-btn{font-family:"Rubik",sans-serif}.grecaptcha-badge{visibility:hidden}.hero-critical,h1.hero-critical,section h1.hero-critical{font-family:"Rubik",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif!important;font-size:2.5rem!important;font-weight:700!important;line-height:1.2!important;color:#02422a!important;margin:0!important}.hero-critical mark::before,.hero-critical [class*="Mark_"]::before,.hero-critical [class*="HightlightWavy"]::before,.hero-critical [class*="Mark_Pink"]::before{display:none!important}.hero-critical mark,.hero-critical [class*="Mark_"]{background:transparent!important;color:inherit!important;position:relative!important}.hero-critical mark::after,.hero-critical [class*="Mark_"]::after{content:""!important;position:absolute!important;top:20%!important;left:-2px!important;right:-2px!important;bottom:10%!important;background:rgba(26,26,26,.08)!important;border-radius:4px!important;z-index:-1!important}@media (min-width:768px){.hero-critical,h1.hero-critical,section h1.hero-critical{font-size:3rem!important}}</style><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/><link rel="dns-prefetch" href="//fonts.gstatic.com"/><link rel="preconnect" href="https://www.google.com"/><link rel="preconnect" href="https://www.gstatic.com" crossorigin="anonymous"/><link rel="dns-prefetch" href="//www.googletagmanager.com"/><link rel="preconnect" href="https://xfpsta639gh5iu7jp-1.a1.typesense.net"/><link rel="dns-prefetch" href="//xfpsta639gh5iu7jp-1.a1.typesense.net"/><link rel="preconnect" href="https://d2e6ccujb3mkqf.cloudfront.net"/><link rel="dns-prefetch" href="//d2e6ccujb3mkqf.cloudfront.net"/><link rel="preconnect" href="https://oggoqwmaeps6otwt.public.blob.vercel-storage.com" crossorigin="anonymous"/><link rel="dns-prefetch" href="//oggoqwmaeps6otwt.public.blob.vercel-storage.com"/><link rel="preconnect" href="https://www.googletagmanager.com"/><link rel="preconnect" href="https://www.google-analytics.com"/><link rel="dns-prefetch" href="//www.google-analytics.com"/><link rel="preconnect" href="https://cdn.cookie-script.com"/><link rel="preconnect" href="https://consent.cookie-script.com"/><link rel="dns-prefetch" href="//cdn.cookie-script.com"/><link rel="dns-prefetch" href="//consent.cookie-script.com"/><link rel="preload" href="/fonts/rubik-variable.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="/fonts/manrope-variable.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/><link rel="preload" href="https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxK.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="preload" href="https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fBBc4.woff2" as="font" type="font/woff2" crossorigin="anonymous"/><link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96"/><link rel="icon" type="image/svg+xml" href="/favicon.svg"/><link rel="shortcut icon" href="/favicon.ico"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"/><meta name="apple-mobile-web-app-title" content="Combak"/><link rel="manifest" href="/site.webmanifest"/><link rel="preload" href="/_next/static/css/e705428f2ee24242.css" as="style"/><link rel="stylesheet" href="/_next/static/css/e705428f2ee24242.css" data-n-g=""/><link rel="preload" href="/_next/static/css/dc9e572b0f9edb48.css" as="style"/><link rel="stylesheet" href="/_next/static/css/dc9e572b0f9edb48.css"/><link rel="preload" href="/_next/static/css/17b4ab0f710c9b7a.css" as="style"/><link rel="stylesheet" href="/_next/static/css/17b4ab0f710c9b7a.css"/><link rel="preload" href="/_next/static/css/12e3ce1ceec88404.css" as="style"/><link rel="stylesheet" href="/_next/static/css/12e3ce1ceec88404.css"/><noscript data-n-css=""></noscript>
22<script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script>
22<script src="/_next/static/chunks/webpack-2186dca6759fa6f3.js" defer=""></script>
22<script src="/_next/static/chunks/framework-7c3854d185585de2.js" defer=""></script>
22<script src="/_next/static/chunks/main-ad142f15e75f7f25.js" defer=""></script>
22<script src="/_next/static/chunks/pages/_app-86d8575ccc234e6a.js" defer=""></script>
22<script src="/_next/static/chunks/07877efe-e2f122407ac86ead.js" defer=""></script>
22<script src="/_next/static/chunks/7112-5160b2a7f98a41d1.js" defer=""></script>
22<script src="/_next/static/chunks/3451-68a1093c3aab0cc7.js" defer=""></script>
22<script src="/_next/static/chunks/5704-75817181e4423432.js" defer=""></script>
22<script src="/_next/static/chunks/6094-0bc8a57d9aa15214.js" defer=""></script>
22<script src="/_next/static/chunks/3670-0770986bfb97bd89.js" defer=""></script>
22<script src="/_next/static/chunks/8644-5d5c5b9c1217589d.js" defer=""></script>
22<script src="/_next/static/chunks/3377-5c01ffcae47b6bf4.js" defer=""></script>
22<script src="/_next/static/chunks/7000-b83dbd2e170ba792.js" defer=""></script>
22<script src="/_next/static/chunks/2736-b9ed53ecd4fd2da0.js" defer=""></script>
22<script src="/_next/static/chunks/593-2acb89f4414480a4.js" defer=""></script>
22<script src="/_next/static/chunks/9054-133cc8e46b5004a0.js" defer=""></script>
22<script src="/_next/static/chunks/7104-b7d8ccc477bdecca.js" defer=""></script>
22<script src="/_next/static/chunks/7903-45fccf2945391f71.js" defer=""></script>
22<script src="/_next/static/chunks/1289-90471dc52f3fa58d.js" defer=""></script>
22<script src="/_next/static/chunks/1885-68eceb667613da9b.js" defer=""></script>
22<script src="/_next/static/chunks/4099-2ae1b1d49cc3d876.js" defer=""></script>
22<script src="/_next/static/chunks/6634-97e7c4bad38b42eb.js" defer=""></script>
22<script src="/_next/static/chunks/pages/ask-eead7d7e7a7cb51c.js" defer=""></script>
22<script src="/_next/static/A9dYD1Ef65ujfvdKyI6Bz/_buildManifest.js" defer=""></script>
22<script src="/_next/static/A9dYD1Ef65ujfvdKyI6Bz/_ssgManifest.js" defer=""></script>
22<style>.anticon{display:inline-flex;align-items:center;color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-0.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}.anticon >*{line-height:1;}.anticon svg{display:inline-block;}.anticon .anticon .anticon-icon{display:block;}.data-ant-cssinjs-cache-path{content:"21mfza|ant-design-icons|anticon:139pitw";}</style></head><body>
22<script> 23// â Initialiser Consent Mode v2 AVANT GTM 24window.dataLayer = window.dataLayer || []; 25function gtag(){dataLayer.push(arguments);} 26 27// Définir le consentement par défaut (denied pour tout sauf security) 28gtag('consent', 'default', { 29 'ad_storage': 'denied', 30 'ad_user_data': 'denied', 31 'ad_personalization': 'denied', 32 'analytics_storage': 'denied', 33 'functionality_storage': 'denied', 34 'personalization_storage': 'denied', 35 'security_storage': 'granted', // Toujours autorisé 36 'wait_for_update': 500 // Attendre max 500ms pour Cookie-Script 37}); 38 39// â Ãcouter les changements de consentement Cookie-Script 40// 41// â ï¸ BUG CORRIGà (audit 2026-07-27) : l'ancienne version lisait le format 42// CookieScript v1 (state.targeting / state.performance, booléens). La prod est 43// en v2 (currentState() = { action, categories: [] }) â tous les champs lus 44// valaient undefined â cet update poussait TOUT en 'denied', APRÃS (et donc 45// par-dessus) l'update 'granted' de l'intégration Google Consent Mode native 46// de CookieScript. Résultat : GA4/Ads en consent denied même après acceptation 47// complète (vérifié en prod via dataLayer). On parse maintenant les DEUX 48// formats ; l'update devient redondant-mais-cohérent avec l'intégration native 49// (double push identique = inoffensif, et on reste protégé si l'intégration 50// native est désactivée côté dashboard CookieScript). 51function updateConsentFromCookieScript() { 52 if (typeof window.CookieScript === 'undefined') return; 53 if (typeof window.CookieScript.instance === 'undefined') return; 54 55 try { 56 const state = window.CookieScript.instance.currentState(); 57 // v2 : { action, categories: ['performance','targeting','functionality',â¦] } 58 const cats = Array.isArray(state.categories) ? state.categories : null; 59 const inCats = function (keys) { 60 for (var i = 0; i < keys.length; i++) { 61 if (cats.indexOf(keys[i]) !== -1) return true; 62 } 63 return false; 64 }; 65 // v1 (legacy) : booléens à plat sur l'objet state. 66 const targeting = cats ? inCats(['targeting', 'advertisement']) : !!state.targeting; 67 const performance = cats 68 ? inCats(['performance', 'analytics', 'statistics']) 69 : !!state.performance; 70 const functionality = cats 71 ? inCats(['functionality', 'personalization']) 72 : !!state.functionality; 73 74 gtag('consent', 'update', { 75 'ad_storage': targeting ? 'granted' : 'denied', 76 'ad_user_data': targeting ? 'granted' : 'denied', 77 'ad_personalization': targeting ? 'granted' : 'denied', 78 'analytics_storage': performance ? 'granted' : 'denied', 79 'functionality_storage': functionality ? 'granted' : 'denied', 80 'personalization_storage': functionality ? 'granted' : 'denied', 81 }); 82 83 console.log('â Consent Mode v2 updated:', { targeting: targeting, performance: performance, functionality: functionality }); 84 } catch (error) { 85 console.error('â Failed to update consent:', error); 86 } 87} 88 89// Ãcouter les événements Cookie-Script (Save = choix partiels, Reject = refus : 90// absents avant, le refus/choix partiel ne re-synchronisait jamais le consent). 91if (typeof window !== 'undefined') { 92 window.addEventListener('CookieScriptLoaded', updateConsentFromCookieScript); 93 window.addEventListener('CookieScriptAccept', updateConsentFromCookieScript); 94 window.addEventListener('CookieScriptAcceptAll', updateConsentFromCookieScript); 95 window.addEventListener('CookieScriptSave', updateConsentFromCookieScript); 96 window.addEventListener('CookieScriptReject', updateConsentFromCookieScript); 97 98 // Vérifier aussi après un court délai (si Cookie-Script était déjà chargé) 99 setTimeout(updateConsentFromCookieScript, 100); 100} 101</script>
101<script> 102 (function() { 103 document.documentElement.classList.add('js-enabled'); 104 105 // â Cacher immédiatement avec CSS pour éviter FOUC 106 var style = document.createElement('style'); 107 style.id = 'ssr-hide-style'; 108 style.innerHTML = 'html.js-enabled .ssr-only, html.js-enabled aside.ssr-only, html.js-enabled div.ssr-only { display: none !important; visibility: hidden !important; }'; 109 document.head.appendChild(style); 110 111 // â Supprimer du DOM après l'hydratation React (éviter contenu dupliqué SEO) 112 // Attendre 100ms après le chargement complet pour laisser React s'hydrater 113 window.addEventListener('load', function() { 114 setTimeout(function() { 115 document.querySelectorAll('.ssr-only').forEach(function(el) { 116 el.remove(); 117 }); 118 }, 100); 119 }); 120 })(); 121 </script>
121<script> 122(function fixCookieScript() { 123 var fixAttempts = 0; 124 var MAX_ATTEMPTS = 50; 125 126 function applyFix() { 127 fixAttempts++; 128 var allCookieElements = Array.from(document.querySelectorAll('[id*="cookie"]')); 129 130 if (allCookieElements.length > 0) { 131 // La fenêtre de détails plein écran ouverte par l'utilisateur 132 // (« Afficher les détails ») : c'est un VRAI modal, il ne faut JAMAIS 133 // le neutraliser ni neutraliser ses descendants, sinon ses boutons 134 // (Accepter / Refuser / Sauvegarder), son close X et ses toggles 135 // deviennent non cliquables. 136 var fsd = document.getElementById('cookiescript_injected_fsd'); 137 138 allCookieElements.forEach(function(el) { 139 // Ne pas toucher la fenêtre de détails ni son contenu. 140 if (fsd && (el === fsd || fsd.contains(el))) return; 141 142 var style = window.getComputedStyle(el); 143 var rect = el.getBoundingClientRect(); 144 var coversScreen = rect.width > window.innerWidth - 100 && rect.height > window.innerHeight - 100; 145 146 if (coversScreen && style.position === 'fixed') { 147 el.style.pointerEvents = 'none'; 148 el.style.setProperty('pointer-events', 'none', 'important'); 149 } 150 151 var children = el.querySelectorAll('*'); 152 children.forEach(function(child) { 153 // Idem : ne jamais désactiver un descendant de la fenêtre de détails. 154 if (fsd && (child === fsd || fsd.contains(child))) return; 155 156 var childStyle = window.getComputedStyle(child); 157 var childRect = child.getBoundingClientRect(); 158 var childCoversScreen = childRect.width > window.innerWidth - 100 && childRect.height > window.innerHeight - 100; 159 160 if (childCoversScreen && childStyle.position === 'fixed') { 161 child.style.pointerEvents = 'none'; 162 child.style.setProperty('pointer-events', 'none', 'important'); 163 } 164 }); 165 }); 166 167 // S'assurer que la fenêtre de détails et tout son contenu restent cliquables. 168 if (fsd) { 169 fsd.style.setProperty('pointer-events', 'auto', 'important'); 170 fsd.querySelectorAll('*').forEach(function(child) { 171 child.style.setProperty('pointer-events', 'auto', 'important'); 172 }); 173 } 174 175 var cookieScriptMain = document.getElementById('cookiescript_injected'); 176 if (cookieScriptMain) { 177 cookieScriptMain.style.zIndex = '10000'; 178 cookieScriptMain.style.setProperty('z-index', '10000', 'important'); 179 180 var visibleBanners = cookieScriptMain.querySelectorAll('[class*="banner"], [class*="dialog"], [id*="dialog"]'); 181 visibleBanners.forEach(function(banner) { 182 banner.style.pointerEvents = 'auto'; 183 banner.style.setProperty('pointer-events', 'auto', 'important'); 184 }); 185 } 186 187 return true; 188 } 189 190 if (fixAttempts < MAX_ATTEMPTS) { 191 setTimeout(applyFix, 100); 192 } 193 194 return false; 195 } 196 197 var observer = new MutationObserver(function(mutations) { 198 mutations.forEach(function(mutation) { 199 mutation.addedNodes.forEach(function(node) { 200 if (node.nodeType === 1) { 201 var el = node; 202 // el.id n'est pas toujours une string : sur certains noeuds (SVG hérités, 203 // DOM clobbering d'un descendant name="id"...) c'est un objet sans .includes 204 // â TypeError répété dans le MutationObserver. On garde-type avant l'appel. 205 if (el.id && typeof el.id === 'string' && el.id.includes('cookiescript')) { 206 setTimeout(applyFix, 50); 207 } 208 } 209 }); 210 }); 211 }); 212 213 if (document.body) { 214 observer.observe(document.body, { 215 childList: true, 216 subtree: false 217 }); 218 } 219 220 if (document.readyState === 'loading') { 221 document.addEventListener('DOMContentLoaded', applyFix); 222 } else { 223 applyFix(); 224 } 225 226 window.addEventListener('load', function() { 227 setTimeout(applyFix, 100); 228 setTimeout(applyFix, 500); 229 setTimeout(applyFix, 1000); 230 }); 231})(); 232</script>
vendor: 67 bytes, line 232
232<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
232GTM-TGT8LCMF
vendor: 82 bytes, line 232
232" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
232<div id="__next"></div>
232<script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/ask","query":{},"buildId":"A9dYD1Ef65ujfvdKyI6Bz","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[{"src":"https://www.dwin2.com/pub.1579424.min.js","strategy":"lazyOnload"}]}</script>
232</body></html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.